Lat*_*suj 1 javascript vb.net encryption rijndael node.js
我有一项有趣的任务要为我的一位客户做...我应该在我为他构建的应用程序上使用此应用程序之一的帐户。之前的应用程序是用VB编写的,并使用以下函数对密码数据进行加密:
Public Function Encrypt(ByVal plainText As String) As String
Dim passPhrase As String = "minePassPhrase"
Dim saltValue As String = "mySaltValue"
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 2
Dim initVector As String = "@1B2c3D4e5F6g7H8"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
Dim password As New PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
Dim memoryStream As New MemoryStream()
Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte() = memoryStream.ToArray()
memoryStream.Close()
cryptoStream.Close()
Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
Return cipherText
End Function
Run Code Online (Sandbox Code Playgroud)
我不是节点密码的专业人士,但经过一些研究,我得出以下结论:
const crypto = require('crypto');
const encrypt = function (data) {
const passPhrase = "minePassPhrase";
const hashAlgorithm = "SHA1";
const passwordIterations = 2;
const keySize = 256;
const initVector = "@1B2c3D4e5F6g7H8";
const saltValue = "mySaltValue";
const initVectorBytes = Buffer.from(initVector.substring(0, 32),"binary");
const saltValueBytes = Buffer.from(saltValue.substring(0, 32),"binary");
const derivedBytes = crypto.pbkdf2Sync(passPhrase, saltValueBytes, passwordIterations, keySize, hashAlgorithm);
const key = derivedBytes.slice(0, Math.floor( keySize / 8 ));
const cipher = crypto.createCipheriv('aes-256-cbc', key, initVectorBytes);
const output = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
return output.toString('base64');
}
Run Code Online (Sandbox Code Playgroud)
为了帮助我,客户给了我一个字符串编码,其中包含 VB 加密的代码。使用VB:“密码”=>“IMY4Jo6BkjDPYXR6DK+rhw==”
如果我尝试使用我的javascript函数:“Password”=>“dkofR4Us7O8+rdeIRsg78w==”
我显然错过了一些东西来获得与 VB 函数相同的结果。但经过几天的研究,我独自一人失去了理智。你有什么主意吗 ?
该问题是由不同的密钥派生函数引起的。在VB代码中PasswordDeriveBytes使用的是基于PBKDF1的。PBKDF1 在RFC 2898 第 5.1 节中定义。生成的密钥的长度对应于所使用的摘要的长度,即 SHA1 为 20 个字节。MS 扩展了该算法,以便还可以生成更长的密钥,例如发布代码中的 32 字节。然而,这意味着 MS 实现不再符合标准,因此跨平台并不总是能找到对应的。幸运的是,NodeJS 的情况有所不同,这里有一个实现,请参见jheys /derive-password-bytes。
以下节点实现重现了 VB 代码的结果:
const derp = require('derive-password-bytes');
const crypto = require('crypto');
const encrypt = function (data) {
const passPhrase = "minePassPhrase";
const hashAlgorithm = "SHA1";
const passwordIterations = 2;
const keySize = 256;
const saltValue = "mySaltValue";
const key = derp(passPhrase, saltValue, passwordIterations, hashAlgorithm, 32);
const initVector = "@1B2c3D4e5F6g7H8";
const initVectorBytes = Buffer.from(initVector, "binary");
const cipher = crypto.createCipheriv('aes-256-cbc', key, initVectorBytes);
const output = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);
return output.toString('base64');
}
const plaintext = "Password"
var encrypted = encrypt(plaintext);
console.log(encrypted);
Run Code Online (Sandbox Code Playgroud)
在新代码中,应使用 PBKDF2 代替 PBKDF1(或PasswordDeriveBytes)。PBKDF2 也在RFC 2898 第 5.2 节中定义。Rfc2898DeriveBytes这里MS提供了符合标准的实现。在发布的 NodeJS 代码中使用了 PBKDF2,这是更安全的实现,但与(可能是遗留的)VB 代码中使用的 PBKDF1 不兼容。关于这两种算法的详细且富有启发性的讨论可以在 04/2004 的MS 博客中找到。
| 归档时间: |
|
| 查看次数: |
723 次 |
| 最近记录: |