解决方法
一个响应建议将RijndaelManaged类包装在COM中.您还可以在COM中包装其他AES实现.我刚刚尝试了
SlowAES,这是AES的JavaScript实现.通过Windows脚本组件将其包装在COM中可以从VBScript调用.我只会在不能使用.NET方法时推荐这个;我猜想AES的.NET将比在JavaScript中实现的AES更快.
在我对COM-wrapped-SlowAEs的测试中,我使用CBC模式,加密与.NET中的RijndaelManaged类完全兼容.
这是WSC;我省略了SlowAES提供的3个.js文件.您需要在我标记文件时不变地插入它们.
<?xml version="1.0"?> <!-- // // Ionic.COM.SlowAES.wsc // // This is a Windows Script Component that exposes the SlowAES // encryption engine via COM. This AES can be used from any // COM-capable environment,including Javascript or VBScript. // // // This code is licensed under the Microsoft Public License. See the // accompanying License.txt file for details. // // copyright 2009 Dino Chiesa // --> <package> <component id="Ionic.Com.SlowAES"> <comment> SlowAES is a Javascript implementation of AES. See http://code.google.com/p/slowaes. This is a COM package for SlowAES. </comment> <?component error="true" debug="true"?> <registration description="WSC Component for SlowAES" progid="Ionic.Com.SlowAES" version="1.00" classid="{ba78383f-1bcc-4df6-9fb9-61cd639ebc94}" remotable="False"> <!-- boilerplate registration/unregistration logic --> <script language="VBScript"> <![CDATA[ strComponent = "Ionic SlowAES" Function Register MsgBox strComponent & " - registered." End Function Function Unregister MsgBox strComponent & " - unregistered." End Function ]]> </script> </registration> <public> <method name="EncryptString"> <parameter name="plainText"/> </method> <method name="DecryptBytes"> <parameter name="cipherText"/> </method> <method name="DecryptBytesToString"> <parameter name="cipherText"/> </method> <method name="DecryptHexString"> <parameter name="hexStringCipherText"/> </method> <method name="DecryptCommaDelimitedStringToString"> <parameter name="cipherText"/> </method> <property name="Key"> <put/> </property> <property name="Mode"> <put/> <get/> </property> <property name="IV"> <put/> <get/> </property> <property name="KeySize"> <put/> <get/> </property> </public> <script language="JavaScript"> <![CDATA[ // ...insert slowAES code here... // // defaults var _keysize = slowAES.aes.SIZE_128; var _mode = slowAES.modeOfOperation.CBC; var _iv = [0,0]; var _key; /* * byteArrayToHexString * convert a byte array to hex string. */ function byteArrayToHexString(a) { try { hexcase } catch(e) { hexcase=0; } var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var r= ""; for (var i = 0; i < a.length; i++) { var b = hex_tab.charat((a[i] >> 4) & 0x0F) + hex_tab.charat(a[i] & 0x0F); r+= b; } return r; } /* * hexStringToByteArray * convert a string of hex byts to a byte array */ function hexStringToByteArray(s) { var r= Array(s.length/2); for (var i = 0; i < s.length; i+=2) { r[i/2] = parseInt(s.substr(i,2),16); } return r; } function EncryptString(plainText) { var bytesToEncrypt = cryptoHelpers.convertStringToByteArray(plainText); var result = slowAES.encrypt(bytesToEncrypt,_mode,_key,_keysize,_iv); return result['cipher']; } function DecryptBytesToString(cipherText) { var d = DecryptBytes(cipherText); var s = cryptoHelpers.convertByteArrayToString(d); s[cipherText.length]= 0; return s; } function DecryptHexString(hexStringCipherText) { var cipherText = hexStringToByteArray(hexStringCipherText); return DecryptBytesToString(cipherText); } function DecryptCommaDelimitedStringToString(cipherText) { var c = []; var atoms = cipherText.split(","); for (i=0; i < atoms.length; i++) { c.push(parseInt(atoms[i],10)); } var d = DecryptBytes(c); return cryptoHelpers.convertByteArrayToString(d); } function DecryptBytes(cipherText) { if (cipherText == undefined) return null; var originalSize = cipherText.length; var result = slowAES.decrypt(cipherText,originalSize,_iv); return result; } function put_Key(keyString) { _key = hexStringToByteArray(keyString); } function put_KeySize(size) { if (size == 128) _keysize = slowAES.aes.keySize.SIZE_128; else if (size == 192) _keysize = slowAES.aes.keySize.SIZE_192; else if (size == 256) _keysize = slowAES.aes.keySize.SIZE_256; else throw "Unsupported key size. Must be one of { 128,192,256 }."; } function get_KeySize() { if (_keysize == slowAES.aes.keySize.SIZE_128) return 128; else if (_keysize == slowAES.aes.keySize.SIZE_192) return 192; else if (_keysize == slowAES.aes.keySize.SIZE_256) return 256; else return -1; } function put_IV(ivString) { _iv = hexStringToByteArray(ivString); } function get_IV() { return byteArrayToHexString(_iv); } function put_Mode(mode) { if (mode == "CBC") _mode= slowAES.modeOfOperation.CBC; else if (mode == "OFB") _mode= slowAES.modeOfOperation.OFB; else if (mode == "CFB") _mode= slowAES.modeOfOperation.CFB; else throw "Unsupported mode. Must be one of {CBC,OFB,CFB}"; } function get_Mode() { if (_mode == slowAES.modeOfOperation.CBC) return "CBC"; if (_mode == slowAES.modeOfOperation.OFB) return "OFB"; if (_mode == slowAES.modeOfOperation.CFB) return "CFB"; return "???"; } ]]> </script> </component> </package>
保存到一个名为SlowAES.wsc的文件.注册“regsvr32 SlowAES.wsc”.
这是一些使用该组件的VBScript代码.
' ' ' byteArrayToHexString' ' convert a byte array to hex string.' ' ' Function byteArrayToHexString(a) Dim r,b,i r = "" For i = 0 To UBound(a) b = Hex( (a(i) And &HF0) / 16) & Hex(a(i) And &HF) r= r & b Next byteArrayToHexString= r End Function ' ' ' hexStringToByteArray' ' convert a string of hex byts to a byte array' ' ' Function hexStringToByteArray(s) Dim r() ReDim r(Len(s)/2-1) Dim x For i = 0 To Len(s)-2 Step 2 x= "&H" & Mid(s,i+1,2) r(i/2) = CInt(x) Next hexStringToByteArray= r End Function Function DemoEncryption() WScript.echo "Testing Ionic.Com.SlowAES..." WScript.echo "key: " & byteArrayToHexString(key) WScript.echo "iv: " & byteArrayToHexString(iv) WScript.echo "key length: " & keyLengthInBytes & " bytes" WScript.echo "key length: " & (keyLengthInBytes*8) & " bits" WScript.echo "plaintext: " & plaintext WScript.echo "plaintext.length: " & Len(plaintext) WScript.echo "instantiate Ionic.Com.SlowAES" Dim aes set aes = CreateObject("Ionic.Com.SlowAES") WScript.echo "keysize" aes.KeySize = keyLengthInBytes * 8 WScript.echo "key" aes.Key = byteArrayToHexString(key) WScript.echo "iv " aes.IV= byteArrayToHexString(iv) WScript.echo "mode " aes.Mode = "CBC" WScript.echo "encrypting... " Dim result result= aes.EncryptString(plaintext) ' result is a comma-separated string ' ' if we Eval() on it we convert it to an array ' Dim expr expr = "Array(" & result & ")" result= Eval( expr ) WScript.echo "Cryptotext/Eval: " & byteArrayToHexString(result) WScript.echo "Cryptotext.length: " & UBound(result)+1 WScript.echo "decrypting... " Dim decrypted 'The javascript way to do this is to pass the byte array.' ' Like so:' ' var decrypted = aes.DecryptBytesToString(result);' ' ' 'This does not work from VBScript. So,convert to a hexstring,' 'pass the hex string,and then convert back,in the COM component.' decrypted= aes.DecryptHexString(byteArrayToHexString(result)) WScript.echo "decrypted: " & decrypted End Function dim plaintext,iv,key,keyLengthInBytes plaintext= "Hello. This is a test. of the emergency broadcasting system." ' iv must be a hexstring representation of an array of bytes,length=16' iv = hexStringToByteArray("FeedbeefFeedbeefbaadf00dbaadf00d") ' key must be a hexstring representation of an array of bytes,length=16 or 32' key = hexStringToByteArray("cafebabe0099887766554433221100AA") keyLengthInBytes= UBound(key)+1 If Err.Number <> 0 Then Err.Clear Call DemoEncryption If (Err.Number <> 0) Then WScript.echo("Error: " & Err.Description)
如果您还需要基于密码的密钥导出功能,那么可以抓取the very succint JavaScript code for PBKDF2 here和create another WSC for that,而不会有太多麻烦.
编辑:我做了我所描述的 – 抓住了PBKDF2的源码,并将其整合到了SlowAES的代码中.我还在C#中生成了第二个独立的实现,它使用内置的.NET类库来执行RFC 2898密钥派生和AES加密.
结果是3个测试应用程序,一个在C#中,一个在JavaScript中,另一个在VBScript中.他们都采取同样的论据.它们各自使用符合RFC 2898标准的密钥导出功能.您可以指定密码,salt,IV和明文,以及在PBKDF2中使用的RFC 2898迭代次数.您可以轻松地验证每个测试程序的密文是否相同.也许这个例子对于某人是有用的.