我想使用C#加密数据并使用JS解密它。
此表表明AES-GCM是使用WebCryptoApi https://diafygi.github.io/webcrypto-examples/的方法 。
我成功地使用BouncyCastle https://codereview.stackexchange.com/questions/14892/simplified-secure-encryption-of-a-string在.NET中加密(和解密)。
var message = "This is the test message"; var key = AESGCM.NewKey(); Console.Out.WriteLine("KEY:" + Convert.ToBase64String(key)); >> KEY:5tgX6AOHot1T9SrImyILIendQXwfdjfOSRAVfMs0ed4= string encrypted = AESGCM.SimpleEncrypt(message, key); Console.Out.WriteLine("ENCRYPTED:" + encrypted); >> ENCRYPTED:Ct0/VbOVsyp/LMxaaFqKKw91+ts+8uzDdHLrTG1XVjPNL7KiBGYB4kfdNGl+xj4fYqdb4JXgdTk= var decrypted = AESGCM.SimpleDecrypt(encrypted, key); Console.Out.WriteLine("DECRYPTED:" + decrypted); >> DECRYPTED:This is the test message但是,我无法弄清楚如何解密这个客户端。 在https://github.com/diafygi/webcrypto-examples#aes-cbc---decrypt上有很多WebCryptoApi示例,包括AES-GCM。
第一步(似乎工作)是导入密钥,我有一个base-64编码的字符串:
var keyString = "+6yDdIiJJl8Lqt60VOHuP25p4yNxz0CRMoE/WKA+Mqo="; function _base64ToArrayBuffer(base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array( len ); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; } var key = _base64ToArrayBuffer(keyString ) var cryptoKey; // we'll get this out in the promise below window.crypto.subtle.importKey( "raw", key, { //this is the algorithm options name: "AES-GCM", }, true, // whether the key is extractable ["encrypt", "decrypt"] // usages ) .then(function(key){ //returns the symmetric key console.log(key); cryptoKey = key; }) .catch(function(err){ console.error(err); });最后一步应该是解密编码消息,该消息也是base-64编码的字符串
var encryptedString = "adHb4UhM93uWyRIV6L1SrYFbxEpIbj3sQW8VwJDP7v+XoxGi6fjmucEEItP1kQWxisZp3qhoAhQ="; var encryptedArrayBuffer = _base64ToArrayBuffer(encryptedString) window.crypto.subtle.decrypt( { name: "AES-GCM", iv: new ArrayBuffer(12), //The initialization vector you used to encrypt //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any) // tagLength: 128, //The tagLength you used to encrypt (if any) }, cryptoKey, //from above encryptedArrayBuffer //ArrayBuffer of the data ) .then(function(decrypted){ //returns an ArrayBuffer containing the decrypted data console.log(new Uint8Array(decrypted)); }) .catch(function(err){ debugger; console.error(err); });不幸的是,这是一个DomError。
我不知道我应该在解密方法中使用“iv”。 我试过null,ArrayBuffer(0),ArrayBuffer(12)。 这几乎是我的理解结束的地方。
I want to encrypt data using C# and decrypt it using JS.
This table suggests that AES-GCM is the way to go with WebCryptoApi https://diafygi.github.io/webcrypto-examples/.
I am successfully using BouncyCastle https://codereview.stackexchange.com/questions/14892/simplified-secure-encryption-of-a-string to encrypt (and decrypt) in .NET.
var message = "This is the test message"; var key = AESGCM.NewKey(); Console.Out.WriteLine("KEY:" + Convert.ToBase64String(key)); >> KEY:5tgX6AOHot1T9SrImyILIendQXwfdjfOSRAVfMs0ed4= string encrypted = AESGCM.SimpleEncrypt(message, key); Console.Out.WriteLine("ENCRYPTED:" + encrypted); >> ENCRYPTED:Ct0/VbOVsyp/LMxaaFqKKw91+ts+8uzDdHLrTG1XVjPNL7KiBGYB4kfdNGl+xj4fYqdb4JXgdTk= var decrypted = AESGCM.SimpleDecrypt(encrypted, key); Console.Out.WriteLine("DECRYPTED:" + decrypted); >> DECRYPTED:This is the test messageBut, I can't figure out how to decrypt this client side. There's a great list of WebCryptoApi examples including AES-GCM at https://github.com/diafygi/webcrypto-examples#aes-cbc---decrypt.
First step (which seems to working) is to import the key, which I have as a base-64 encoded string:
var keyString = "+6yDdIiJJl8Lqt60VOHuP25p4yNxz0CRMoE/WKA+Mqo="; function _base64ToArrayBuffer(base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array( len ); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; } var key = _base64ToArrayBuffer(keyString ) var cryptoKey; // we'll get this out in the promise below window.crypto.subtle.importKey( "raw", key, { //this is the algorithm options name: "AES-GCM", }, true, // whether the key is extractable ["encrypt", "decrypt"] // usages ) .then(function(key){ //returns the symmetric key console.log(key); cryptoKey = key; }) .catch(function(err){ console.error(err); });The final step should be to decrypt the encoded message, which is also a base-64 encoded string
var encryptedString = "adHb4UhM93uWyRIV6L1SrYFbxEpIbj3sQW8VwJDP7v+XoxGi6fjmucEEItP1kQWxisZp3qhoAhQ="; var encryptedArrayBuffer = _base64ToArrayBuffer(encryptedString) window.crypto.subtle.decrypt( { name: "AES-GCM", iv: new ArrayBuffer(12), //The initialization vector you used to encrypt //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any) // tagLength: 128, //The tagLength you used to encrypt (if any) }, cryptoKey, //from above encryptedArrayBuffer //ArrayBuffer of the data ) .then(function(decrypted){ //returns an ArrayBuffer containing the decrypted data console.log(new Uint8Array(decrypted)); }) .catch(function(err){ debugger; console.error(err); });Unfortunately, this is thowing a DomError.
I have no idea what I am supposed to use for "iv" in the decrypt method. I've tried null, ArrayBuffer(0), ArrayBuffer(12). This is pretty much where my understanding ends.
最满意答案
如果你研究AESGCM的实现,你应该看到nonce(称为IV)是密文的一部分。 其大小设置为16个字节( NonceBitSize = 128 )。 您需要从JavaScript中的密文开头读取那么多字节,并使用剩余的字节作为要解密的实际密文。
GCM仅定义为96位的随机数,因此您可能需要将其更改为NonceBitSize = 96并读取前12个字节。
根据这个答案 ,您需要为认证标签切片密文的最后16个字节( MacBitSize = 128 )。
96位随机数的示例:
window.crypto.subtle.decrypt( { name: "AES-GCM", iv: encryptedArrayBuffer.slice(0, 12), //The initialization vector you used to encrypt //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any) // tagLength: 128, //The tagLength you used to encrypt (if any) tag: encryptedArrayBuffer.slice(-16), // authentication tag }, cryptoKey, //from above encryptedArrayBuffer.slice(12, -16) //ArrayBuffer of the data // alternatively: encryptedArrayBuffer.slice(12) // in some cases leave the authentication tag in place )If you look into the implementation of AESGCM, you should see that the nonce (called IV) is part of the ciphertext. Its size is set to 16 bytes (NonceBitSize = 128). You would need to read that many bytes from the beginning of the ciphertext in JavaScript and use the remaining bytes as the actual ciphertext to be decrypted.
GCM is only defined for a nonce of 96 bit, so you might need to change it to NonceBitSize = 96 and read the first 12 bytes.
Based on this answer, you will need to slice the last 16 bytes of the ciphertext (MacBitSize = 128) for the authentication tag.
Example with a 96 bit nonce:
window.crypto.subtle.decrypt( { name: "AES-GCM", iv: encryptedArrayBuffer.slice(0, 12), //The initialization vector you used to encrypt //additionalData: ArrayBuffer, //The addtionalData you used to encrypt (if any) // tagLength: 128, //The tagLength you used to encrypt (if any) tag: encryptedArrayBuffer.slice(-16), // authentication tag }, cryptoKey, //from above encryptedArrayBuffer.slice(12, -16) //ArrayBuffer of the data // alternatively: encryptedArrayBuffer.slice(12) // in some cases leave the authentication tag in place )
更多推荐
发布评论