【问题标题】:How can i encrypt by postgres and decrypt by c#?我如何通过 postgres 加密并通过 c# 解密?
【发布时间】:2019-08-28 21:13:23
【问题描述】:

我在 postgres 中加密密码 我想用c#解密它,但是两种方法不匹配 .我该怎么做?

private static byte[] TruncateHash(string key, int length)
{
    SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
    // Hash the key.
    byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(key);
    byte[] hash = sha1.ComputeHash(keyBytes);

    // Truncate or pad the hash.
    Array.Resize(ref hash, length);
    return hash;
}

public static string EncryptString(string plaintext, string Passphrase)
{
    TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
    // Initialize the crypto provider.
    tripleDes.Key = TruncateHash(Passphrase, tripleDes.KeySize / 8);
    tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);

    // Convert the plaintext string to a byte array.
    byte[] plaintextBytes = System.Text.Encoding.Unicode.GetBytes(plaintext);

    // Create the stream.
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    // Create the encoder to write to the stream.
    CryptoStream encStream = new CryptoStream(ms, tripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

    // Use the crypto stream to write the byte array to the stream.
    encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
    encStream.FlushFinalBlock();

    // Convert the encrypted stream to a printable string.
    return Convert.ToBase64String(ms.ToArray());
}

public static string DecryptString(string encryptedtext, string Passphrase)
{
    TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
    // Initialize the crypto provider.
    tripleDes.Key = TruncateHash(Passphrase, tripleDes.KeySize / 8);
    tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);
    // Convert the encrypted text string to a byte array.
    byte[] encryptedBytes = Convert.FromBase64String(encryptedtext);

    // Create the stream.
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    // Create the decoder to write to the stream.
    CryptoStream decStream = new CryptoStream(ms, tripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

    // Use the crypto stream to write the byte array to the stream.
    decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
    decStream.FlushFinalBlock();

    // Convert the plaintext stream to a string.
    return System.Text.Encoding.Unicode.GetString(ms.ToArray());
}

我找到了一种使用 pgcrypto 在 postgres 中加密的方法。 以下是postgres中的加密和解密。

SELECT encode(encrypt_iv('ABCDE121212','Key123', '','3des'), 'base64');
select decrypt_iv(decode('jEI4V5q6h5/p12NRJm666g==','base64'),'Key123','','3des')

我的代码有什么问题,c# 和 postgres 不能不匹配。 我想保留 c# 代码并将 postgres 代码更改为匹配

【问题讨论】:

  • 仅供参考,它是“postgres”或“postgresql”,绝不是“postgre”
  • 在您的 C# 应用程序中,您正在从密码创建一个哈希,显然 pgsql 需要一个直接字节数组(我假设 pgsql 只是零填充或修剪提供的密码到所需的长度)。不管怎样,您应该意识到,不使用 IV 也会造成严重的弱点。
  • 怎么做,我无法在 postgres 中转换密码短语与 c# 匹配。在 c# 中,我的密码是字符串并将其转换为 32 字节二进制。在 postgres 中,我找不到相同的方法

标签: c# postgresql encryption


【解决方案1】:

Source Url

加密函数:

public static String AES_encrypt(String input, string key, string Iv, int keyLength)
{
        RijndaelManaged aes = new RijndaelManaged();
        aes.KeySize = keyLength;
        aes.BlockSize = 128;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.Key = mkey(key,keyLength);
        aes.IV = mkey(Iv,128);
        
        var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
        byte[] xBuff = null;

        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
            {
                byte[] xXml = Encoding.UTF8.GetBytes(input);
                cs.Write(xXml, 0, xXml.Length);
                cs.FlushFinalBlock();
            }

            xBuff = ms.ToArray();
        }

        return Convert.ToBase64String(xBuff,Base64FormattingOptions.None);
}

解密函数:

public static String AES_decrypt(String Input, string key, string Iv, int keyLength)
{
        try
        {
            RijndaelManaged aes = new RijndaelManaged();
            aes.KeySize = keyLength;
            aes.BlockSize = 128;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = mkey(key,keyLength);
            aes.IV = mkey(Iv,128);
            
            var decrypt = aes.CreateDecryptor();
            byte[] encryptedStr = Convert.FromBase64String(Input);

            string Plain_Text;

            using (var ms = new MemoryStream(encryptedStr))
            {
                using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Read))
                {
                    using (StreamReader reader = new StreamReader(cs))
                    {
                        Plain_Text = reader.ReadToEnd();
                    }
                }
            }

            return Plain_Text;
        }
        catch (Exception ex)
        {
            return null;
        }
 }

辅助函数:

private static byte[] mkey(string skey, int keyLength)
{
        int length = keyLength / 8;
        byte[] key = Encoding.UTF8.GetBytes(skey);
        byte[] k =  GenerateEmptyArray(length);

        for (int i = 0; i < key.Length; i++)
        {
            //k[i % 16] = (byte)(k[i % 16] ^ key[i]);
            k[i] = key[i];
            if(i == length-1)
                break;
        }

        return k;
    }

变量:

input = "Hello World"
key = "NBJ42RKQ2vQoYFZO"
Iv = "j1C83921vHExVhVp"
keyLength = 128

关于变量的信息:

input - string that is not encrypted or encrypted. If it's encrypted it will be in Base64 format

key - Any Unicode character that will match the AES key size(in this example it's 128). I have written a function that will extract the specific length of characters and add them to a byte array

代码:

public static string PasswordFixer(string skey,int keyLength)
{
        int length = keyLength / 8;
        byte[] key = Encoding.UTF8.GetBytes(skey);
        byte[] k = GenerateEmptyArray(length);

        for (int i = 0; i < key.Length; i++)
        {
            k[i] = key[i];

            if(i == length-1)
                break;
        }

        return Encoding.UTF8.GetString(k);
}

Iv - it's always 128bit long meaning 16bytes. you can ignore Iv if you want, in PostgreSQL if you planing to use `encrypt` function then you can ignore the Iv by hard coding like this `aes.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };`

密钥长度- 这是本例中的 AES 密钥长度,我们使用 128 位表示 16 个字节。无论您用作 Key 的字符都需要匹配 16 个字节的长度。

PostgreSQL

加解密等价的SQL语句是这样的

encrypt_iv,decrypt_iv

select convert_from(decrypt_iv(decode(tbl1.encrypted,'base64')::bytea ,'NBJ42RKQ2vQoYFZO','j1C83921vHExVhVp', 'aes-cbc/pad:pkcs'), 'UTF-8') as decrypted,tbl1.encrypted from (select encode(encrypt_iv('Hello World', 'NBJ42RKQ2vQoYFZO','j1C83921vHExVhVp', 'aes-cbc/pad:pkcs'), 'base64') as encrypted) as tbl1

加密、解密

select convert_from(decrypt(decode(tbl1.encrypted,'base64')::bytea ,'NBJ42RKQ2vQoYFZO', 'aes-cbc/pad:pkcs'), 'UTF-8') as decrypted,tbl1.encrypted from (select encode(encrypt('Hello World', 'NBJ42RKQ2vQoYFZO', 'aes-cbc/pad:pkcs'), 'base64') as encrypted) as tbl1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    相关资源
    最近更新 更多