AES-GCM 需要相同的 init_vector 来自加密进行解密。为什么?
AES-GCM needs the same init_vector from encryption FOR decryption. Why?
我已经尽可能逐字地创建了一个 TypeScript 示例 from MDN example 来进行说明。它加密和解密都很好。我刚刚注意到,要使解密工作,它需要与加密相同的 init_vector
。 init_vector
不是随机数吗?
如果解密,接收消息的人如何知道我用于加密的init_vector
是什么是否在不同的地点和时间完成了一个单独的过程?
const message_plain: string = "Hello World!";
const password_plain: string = "letmein";
// AES-GCM - ENCRYPTION
const pbkdf2_salt: Uint8Array = crypto.getRandomValues(new Uint8Array(16)); // 128 bits
const pbkdf2_iterations: number = 100000;
const init_vector: Uint8Array = crypto.getRandomValues(new Uint8Array(12)); // 96 bits
const utf8_encoder: TextEncoder = new TextEncoder();
const message_bytes: Uint8Array = utf8_encoder.encode(message_plain);
const password_bytes: Uint8Array = utf8_encoder.encode(password_plain);
const crypto_key_material: CryptoKey = await crypto.subtle.importKey(
"raw",
password_bytes,
{ name: "PBKDF2" },
false,
["deriveBits", "deriveKey"],
);
const crypto_key_derived: CryptoKey = await crypto.subtle.deriveKey(
{
"name": "PBKDF2",
salt: pbkdf2_salt,
"iterations": pbkdf2_iterations,
"hash": "SHA-256",
},
crypto_key_material,
{ "name": "AES-GCM", "length": 256 },
true,
["encrypt", "decrypt"],
);
const message_encrypted: ArrayBuffer = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_bytes,
);
const message_encrypted_bytes: Uint8Array = new Uint8Array(message_encrypted);
console.log(
`[${message_encrypted.byteLength} bytes total] -> ${message_encrypted_bytes}`,
);
// AES-GCM - DECRYPTION
const utf8Decoder: TextDecoder = new TextDecoder();
try {
const message_decrypted: ArrayBuffer = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_encrypted,
);
const message_decrypted_bytes: Uint8Array = new Uint8Array(message_decrypted);
console.log(utf8Decoder.decode(message_decrypted_bytes));
} catch (e) {
console.log("*** Decryption error ***");
}
您应该使用非对称加密,例如具有 public / 私钥的 RSA,例如这个 node-rsa 包。
就具有相同的初始向量而言,我发现这段摘自 answer:
In any case, the IV never needs to be kept secret — if it did, it would be a key, not an IV. Indeed, in most cases, keeping the IV secret would not be practical even if you wanted to since the recipient needs to know it in order to decrypt the data (or verify the hash, etc.).
我已经尽可能逐字地创建了一个 TypeScript 示例 from MDN example 来进行说明。它加密和解密都很好。我刚刚注意到,要使解密工作,它需要与加密相同的 init_vector
。 init_vector
不是随机数吗?
如果解密,接收消息的人如何知道我用于加密的init_vector
是什么是否在不同的地点和时间完成了一个单独的过程?
const message_plain: string = "Hello World!";
const password_plain: string = "letmein";
// AES-GCM - ENCRYPTION
const pbkdf2_salt: Uint8Array = crypto.getRandomValues(new Uint8Array(16)); // 128 bits
const pbkdf2_iterations: number = 100000;
const init_vector: Uint8Array = crypto.getRandomValues(new Uint8Array(12)); // 96 bits
const utf8_encoder: TextEncoder = new TextEncoder();
const message_bytes: Uint8Array = utf8_encoder.encode(message_plain);
const password_bytes: Uint8Array = utf8_encoder.encode(password_plain);
const crypto_key_material: CryptoKey = await crypto.subtle.importKey(
"raw",
password_bytes,
{ name: "PBKDF2" },
false,
["deriveBits", "deriveKey"],
);
const crypto_key_derived: CryptoKey = await crypto.subtle.deriveKey(
{
"name": "PBKDF2",
salt: pbkdf2_salt,
"iterations": pbkdf2_iterations,
"hash": "SHA-256",
},
crypto_key_material,
{ "name": "AES-GCM", "length": 256 },
true,
["encrypt", "decrypt"],
);
const message_encrypted: ArrayBuffer = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_bytes,
);
const message_encrypted_bytes: Uint8Array = new Uint8Array(message_encrypted);
console.log(
`[${message_encrypted.byteLength} bytes total] -> ${message_encrypted_bytes}`,
);
// AES-GCM - DECRYPTION
const utf8Decoder: TextDecoder = new TextDecoder();
try {
const message_decrypted: ArrayBuffer = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_encrypted,
);
const message_decrypted_bytes: Uint8Array = new Uint8Array(message_decrypted);
console.log(utf8Decoder.decode(message_decrypted_bytes));
} catch (e) {
console.log("*** Decryption error ***");
}
您应该使用非对称加密,例如具有 public / 私钥的 RSA,例如这个 node-rsa 包。
就具有相同的初始向量而言,我发现这段摘自 answer:
In any case, the IV never needs to be kept secret — if it did, it would be a key, not an IV. Indeed, in most cases, keeping the IV secret would not be practical even if you wanted to since the recipient needs to know it in order to decrypt the data (or verify the hash, etc.).