Предупреждение. :
![enter image description here](https://i.stack.imgur.com/BuqDb.png)
Кроме того, я не являюсь специалистом по безопасности.Все это, как говорится ...
Одним из подходов является генерация ключа на стороне клиента без запроса уникальной строки с внутреннего сервера.Зашифруйте этим ключом, сохраните ключ на своем внутреннем сервере, а затем снова извлеките ключ для расшифровки.
Это в JavaScript и будет работать так же хорошо в TypeScript.
const runDemo = async () => {
const messageOriginalDOMString = 'Do the messages match?';
//
// Encode the original data
//
const encoder = new TextEncoder();
const messageUTF8 = encoder.encode(messageOriginalDOMString);
//
// Configure the encryption algorithm to use
//
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const algorithm = {
iv,
name: 'AES-GCM',
};
//
// Generate/fetch the cryptographic key
//
const key = await window.crypto.subtle.generateKey({
name: 'AES-GCM',
length: 256
},
true, [
'encrypt',
'decrypt'
]
);
//
// Run the encryption algorithm with the key and data.
//
const messageEncryptedUTF8 = await window.crypto.subtle.encrypt(
algorithm,
key,
messageUTF8,
);
//
// Export Key
//
const exportedKey = await window.crypto.subtle.exportKey(
'raw',
key,
);
// This is where to save the exported key to the back-end server,
// and then to fetch the exported key from the back-end server.
//
// Import Key
//
const importedKey = await window.crypto.subtle.importKey(
'raw',
exportedKey,
"AES-GCM",
true, [
"encrypt",
"decrypt"
]
);
//
// Run the decryption algorithm with the key and cyphertext.
//
const messageDecryptedUTF8 = await window.crypto.subtle.decrypt(
algorithm,
importedKey,
messageEncryptedUTF8,
);
//
// Decode the decryped data.
//
const decoder = new TextDecoder();
const messageDecryptedDOMString = decoder.decode(messageDecryptedUTF8);
//
// Assert
//
console.log(messageOriginalDOMString);
console.log(messageDecryptedDOMString);
};
runDemo();
С другой стороны, если в соответствии с требованиями ключ шифрования должен быть получен из уникальной строки с низкой энтропией из серверной части, то deriveKey
метод может быть подходящим с алгоритмом PBKDF2 .
const runDemo = async() => {
const messageOriginalDOMString = 'Do the messages match?';
//
// Encode the original data
//
const encoder = new TextEncoder();
const messageUTF8 = encoder.encode(messageOriginalDOMString);
//
// Configure the encryption algorithm to use
//
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const algorithm = {
iv,
name: 'AES-GCM',
};
//
// Generate/fetch the cryptographic key
//
function getKeyMaterial() {
let input = 'the-username' + new Date();
let enc = new TextEncoder();
return window.crypto.subtle.importKey(
"raw",
enc.encode(input), {
name: "PBKDF2"
},
false, ["deriveBits", "deriveKey"]
);
}
let keyMaterial = await getKeyMaterial();
let salt = window.crypto.getRandomValues(new Uint8Array(16));
let key = await window.crypto.subtle.deriveKey({
"name": "PBKDF2",
salt: salt,
"iterations": 100000,
"hash": "SHA-256"
},
keyMaterial, {
"name": "AES-GCM",
"length": 256
},
true, ["encrypt", "decrypt"]
);
//
// Run the encryption algorithm with the key and data.
//
const messageEncryptedUTF8 = await window.crypto.subtle.encrypt(
algorithm,
key,
messageUTF8,
);
//
// Export Key
//
const exportedKey = await window.crypto.subtle.exportKey(
'raw',
key,
);
// This is where to save the exported key to the back-end server,
// and then to fetch the exported key from the back-end server.
//
// Import Key
//
const importedKey = await window.crypto.subtle.importKey(
'raw',
exportedKey,
"AES-GCM",
true, [
"encrypt",
"decrypt"
]
);
//
// Run the decryption algorithm with the key and cyphertext.
//
const messageDecryptedUTF8 = await window.crypto.subtle.decrypt(
algorithm,
importedKey,
messageEncryptedUTF8,
);
//
// Decode the decryped data.
//
const decoder = new TextDecoder();
const messageDecryptedDOMString = decoder.decode(messageDecryptedUTF8);
//
// Assert
//
console.log(messageOriginalDOMString);
console.log(messageDecryptedDOMString);
};
runDemo();