首页 文章

使用System.Security.Cryptography加密文本以匹配OpenSSL

提问于
浏览
1

我需要正确加密文本(特定密码),以便第三方可以解密它 . 他们为我提供了他们用来解密的密钥,并告诉我他们将使用OpenSSL解密它 .

我一直在尝试使用AESManaged和System.Security.Cryptography中的RijndaelManaged类来创建可解密但不是非常成功的东西 .

他们提供的OpenSSL加密示例如下:

echo“密码”| enc -base64 -aes-256-cbc -k“providedKey”-p -md sha1

所以我需要创建一个CryptoStream,它是一个密钥大小为256的AES加密器,以及一个CBC的密码模式 . 然后base64编码生成的字节数组 . 那部分非常简单 .

我不确定如何创造是关键,我正在寻找正确方向的一点 .

我注意到在OpenSSL中由这些参数创建的所有base64解码文本都以相同的8个字符“Salted__”开头 . 所以我猜这是用来生成密钥的Salt .

任何人都知道如何使用私钥和“Salted__”创建SHA1密钥?

我知道OpenSSL.Net项目包装了OpenSSL dll,但是如果可能的话我想避免走那条路 .

2 回答

  • 2

    感谢GregS's Point in the right direction,很容易复制EVP_BytesToKey()中发生的Key和Initial Vector生成 .

    基本上他们创建了一个48字节的数组(用于密钥的32字节数组和用于IV的16字节数组),并使用SHA1将私钥和8个盐字节散列到该缓冲区中 . 第一个哈希只是私钥和盐,连续哈希是生成的最后一个哈希,它与密钥和盐字节连接起来,直到48字节数组被填满 .

    密钥只是前32个字节,IV是最后16个字节 .

    使用System.Security.Crytpography中的AESManaged类以及从此方法派生的密钥和IV,我能够以使用OpenSSL库的第三方可以解密的方式加密我的密码 .

    这是我用来导出密钥和初始向量的算法:

    /// <summary>
        /// Derives the key and IV.
        /// </summary>
        /// <param name="saltBytes">The salt bytes.</param>
        /// <param name="privateKeyBytes">The private key bytes.</param>
        /// <param name="iv">The iv.</param>
        /// <returns>The Key</returns>
        private static byte[] DeriveKeyAndIV(byte[] saltBytes, byte[] privateKeyBytes, out byte[] iv)
        {
            // we are creating a 16 byte initial vector and a 32 byte key 
            const int ivLength   = 16;
            iv = new byte[ivLength];
            const int keyLength  = 32;
            var key = new byte[keyLength];
    
            //SHA1 creates a 20 byte hash
            const int hashLength = 20;
    
            // container to store the hashed values
            var keyContainer = new byte[keyLength + ivLength];
    
            // munge together the privateKey and salt
            var privateKeyAndSalt = new byte[privateKeyBytes.Length + saltBytes.Length];
            Array.Copy(privateKeyBytes, privateKeyAndSalt, privateKeyBytes.Length);
            Array.Copy(saltBytes, 0, privateKeyAndSalt, privateKeyBytes.Length, saltBytes.Length);
    
            // use SHA1 crypto to match the -md SHA1 command line.
            var sha1 = new SHA1CryptoServiceProvider();
    
            // hashtarget holds the successive hash's source bytes.
            var hashtarget = new byte[hashLength + privateKeyAndSalt.Length];
    
            byte[] currentHash = null;
            var bytesCopied = 0;
    
            // do the hashing until we fill the container
            while (bytesCopied < (ivLength + keyLength))
            {
                // Hash(0) is an empty set so just concatenate private key and salt.
                if (currentHash == null)
                {
                    currentHash = sha1.ComputeHash(privateKeyAndSalt);
                }
                else
                {
                    // successive hashes are done on Hash(prev) + private key + salt.
                    Array.Copy(currentHash, hashtarget, currentHash.Length);
                    Array.Copy(privateKeyAndSalt, 0, hashtarget, currentHash.Length, privateKeyAndSalt.Length);
                    currentHash = hashtarget;
                    currentHash = sha1.ComputeHash(currentHash);
                }
                var copyAmount = Math.Min(currentHash.Length, keyContainer.Length - bytesCopied);
                Array.Copy(currentHash, 0, keyContainer, bytesCopied, copyAmount);
                bytesCopied += copyAmount;
            }
    
            // split out bytes in the container. first 32 are key, last 16 are iv.
            Array.Copy(keyContainer, 0, key, 0, key.Length);
            Array.Copy(keyContainer, key.Length, iv, 0, iv.Length);
    
            return key;
        }
    
  • 1

    我在相关的openssl源( apps/enc.c )中略微探讨了一下,我认为openssl使用了一种有点专有的方法 . 我承认我懒得弄清楚所有的细节,但他们在那里 . 看起来ASCII字符串"Salted__"后跟8个随机盐字节被添加到文件中 . AES密钥和AES iv使用名为EVP_BytesToKey()的openssl方法从密码和salt派生 . 该手册中描述了该算法 . 在版本1.0.0a的 enc.c source code中,此部分从第510行开始 .

    希望这可以帮助你入门 .

相关问题