Как в C#.NET encrypt() затем JS WebCryptoApi расшифровать () с помощью AES-GCM?
Я хочу зашифровать данные с помощью C# и расшифровать его с помощью JS.
Эта таблица показывает, что AES-GCM - это то же самое, что и WebCryptoApi https://diafygi.github.io/webcrypto-examples/.
Я успешно использую https://codereview.stackexchange.com/questions/14892/simplified-secure-encryption-of-a-string для BouncyCastle для шифрования (и дешифрования) в.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
Но я не могу понять, как расшифровать эту клиентскую сторону. Большой список примеров WebCryptoApi, включая AES-GCM, можно найти по адресу https://github.com/diafygi/webcrypto-examples.
Первый шаг (который, кажется, работает) - импортировать ключ, который у меня есть в виде строки в кодировке 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" в методе расшифровки. Я пробовал ноль, ArrayBuffer(0), ArrayBuffer(12). На этом мое понимание заканчивается.
1 ответ
Если вы посмотрите на реализацию AESGCM
Вы должны увидеть, что одноразовый номер (называемый 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
)