字符串的 SubtleCrypto ArrayBuffer 键
SubtleCrypto ArrayBuffer Key to String
我一直在查看 SublteCrypto 到 encrypt/decrypt 文本消息,并想提取用于字符串的密钥,但使用相同的接口 "SubtleCrypto" 会为该密钥生成奇怪的字符串。
现在这是我正在玩的代码:
Internal.crypto = {
getRandomBytes: function(size) {
var array = new Uint8Array(size);
crypto.getRandomValues(array);
return array.buffer;
},
encrypt: function(key, data, iv) {
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['encrypt']).then(function(key) {
return crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
decrypt: function(key, data, iv) {
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['decrypt']).then(function(key) {
return crypto.subtle.decrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
sign: function(key, data) {
return crypto.subtle.importKey('raw', key, {name: 'HMAC', hash: {name: 'SHA-256'}}, false, ['sign']).then(function(key) {
return crypto.subtle.sign( {name: 'HMAC', hash: 'SHA-256'}, key, data);
});
},
hash: function(data) {
return crypto.subtle.digest({name: 'SHA-512'}, data);
},
HKDF: function(input, salt, info) {
// Specific implementation of RFC 5869 that only returns the first 3 32-byte chunks
// TODO: We dont always need the third chunk, we might skip it
return Internal.crypto.sign(salt, input).then(function(PRK) {
var infoBuffer = new ArrayBuffer(info.byteLength + 1 + 32);
var infoArray = new Uint8Array(infoBuffer);
infoArray.set(new Uint8Array(info), 32);
infoArray[infoArray.length - 1] = 1;
return Internal.crypto.sign(PRK, infoBuffer.slice(32)).then(function(T1) {
infoArray.set(new Uint8Array(T1));
infoArray[infoArray.length - 1] = 2;
return Internal.crypto.sign(PRK, infoBuffer).then(function(T2) {
infoArray.set(new Uint8Array(T2));
infoArray[infoArray.length - 1] = 3;
return Internal.crypto.sign(PRK, infoBuffer).then(function(T3) {
return [ T1, T2, T3 ];
});
});
});
});
},
// Curve 25519 crypto
createKeyPair: function(privKey) {
if (privKey === undefined) {
privKey = Internal.crypto.getRandomBytes(32);
}
return Internal.Curve.async.createKeyPair(privKey);
},
ECDHE: function(pubKey, privKey) {
return Internal.Curve.async.ECDHE(pubKey, privKey);
},
Ed25519Sign: function(privKey, message) {
return Internal.Curve.async.Ed25519Sign(privKey, message);
},
Ed25519Verify: function(pubKey, msg, sig) {
return Internal.Curve.async.Ed25519Verify(pubKey, msg, sig);
}
};
我为获取字符串中的密钥所做的更改是:
encrypt: function(key, data, iv) {
var sKey = String.fromCharCode.apply(null, new Uint8Array(key));
console.log('key ' + sKey);
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, true, ['encrypt']).then(function(key) {
return crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
decrypt: function(key, data, iv) {
var sKey = String.fromCharCode.apply(null, new Uint8Array(key));
console.log('key ' + sKey);
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, true, ['decrypt']).then(function(key) {
return crypto.subtle.decrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
}
我知道 encrypt: function(key, data, iv)
中的 key
和 ArrayBuffer 中的 decrypt: function(key, data, iv)
,但我已经尝试了所有从 ArrayBuffer 转换为 String 的方法,但它总是会产生不正确的编码字符串,例如Sask���ç é
加密密钥不是文本,也不是编码为字节的文本。它是一个随机字节序列,因此尝试将其解码为字符串很可能会不可挽回地丢失数据。
而是使用 base-64 编码 (btoa()
) 和解码 (atob()
) 将二进制数据转换为字符串,然后再转换回来。密文也是如此。
我一直在查看 SublteCrypto 到 encrypt/decrypt 文本消息,并想提取用于字符串的密钥,但使用相同的接口 "SubtleCrypto" 会为该密钥生成奇怪的字符串。
现在这是我正在玩的代码:
Internal.crypto = {
getRandomBytes: function(size) {
var array = new Uint8Array(size);
crypto.getRandomValues(array);
return array.buffer;
},
encrypt: function(key, data, iv) {
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['encrypt']).then(function(key) {
return crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
decrypt: function(key, data, iv) {
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, false, ['decrypt']).then(function(key) {
return crypto.subtle.decrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
sign: function(key, data) {
return crypto.subtle.importKey('raw', key, {name: 'HMAC', hash: {name: 'SHA-256'}}, false, ['sign']).then(function(key) {
return crypto.subtle.sign( {name: 'HMAC', hash: 'SHA-256'}, key, data);
});
},
hash: function(data) {
return crypto.subtle.digest({name: 'SHA-512'}, data);
},
HKDF: function(input, salt, info) {
// Specific implementation of RFC 5869 that only returns the first 3 32-byte chunks
// TODO: We dont always need the third chunk, we might skip it
return Internal.crypto.sign(salt, input).then(function(PRK) {
var infoBuffer = new ArrayBuffer(info.byteLength + 1 + 32);
var infoArray = new Uint8Array(infoBuffer);
infoArray.set(new Uint8Array(info), 32);
infoArray[infoArray.length - 1] = 1;
return Internal.crypto.sign(PRK, infoBuffer.slice(32)).then(function(T1) {
infoArray.set(new Uint8Array(T1));
infoArray[infoArray.length - 1] = 2;
return Internal.crypto.sign(PRK, infoBuffer).then(function(T2) {
infoArray.set(new Uint8Array(T2));
infoArray[infoArray.length - 1] = 3;
return Internal.crypto.sign(PRK, infoBuffer).then(function(T3) {
return [ T1, T2, T3 ];
});
});
});
});
},
// Curve 25519 crypto
createKeyPair: function(privKey) {
if (privKey === undefined) {
privKey = Internal.crypto.getRandomBytes(32);
}
return Internal.Curve.async.createKeyPair(privKey);
},
ECDHE: function(pubKey, privKey) {
return Internal.Curve.async.ECDHE(pubKey, privKey);
},
Ed25519Sign: function(privKey, message) {
return Internal.Curve.async.Ed25519Sign(privKey, message);
},
Ed25519Verify: function(pubKey, msg, sig) {
return Internal.Curve.async.Ed25519Verify(pubKey, msg, sig);
}
};
我为获取字符串中的密钥所做的更改是:
encrypt: function(key, data, iv) {
var sKey = String.fromCharCode.apply(null, new Uint8Array(key));
console.log('key ' + sKey);
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, true, ['encrypt']).then(function(key) {
return crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
},
decrypt: function(key, data, iv) {
var sKey = String.fromCharCode.apply(null, new Uint8Array(key));
console.log('key ' + sKey);
return crypto.subtle.importKey('raw', key, {name: 'AES-CBC'}, true, ['decrypt']).then(function(key) {
return crypto.subtle.decrypt({name: 'AES-CBC', iv: new Uint8Array(iv)}, key, data);
});
}
我知道 encrypt: function(key, data, iv)
中的 key
和 ArrayBuffer 中的 decrypt: function(key, data, iv)
,但我已经尝试了所有从 ArrayBuffer 转换为 String 的方法,但它总是会产生不正确的编码字符串,例如Sask���ç é
加密密钥不是文本,也不是编码为字节的文本。它是一个随机字节序列,因此尝试将其解码为字符串很可能会不可挽回地丢失数据。
而是使用 base-64 编码 (btoa()
) 和解码 (atob()
) 将二进制数据转换为字符串,然后再转换回来。密文也是如此。