var parametros = {
name: "DH",
// NOTA: ESSE É UM PRIMO PEQUENO PARA TESTES SOMENTE! NÃO USE NA PRÁTICA!
// Ver http://datatracker.ietf.org/doc/rfc3526/ para primos melhores
prime: new Uint8Array([255,255,255,255,255,255,255,255,201,15,218,162,33,104,194,52,196,198,98,139, 128,220,28,209,41,2,78,8,138,103,204,116,2,11,190,166,59,19,155,34,81,74,8, 121,142,52,4,221,239,149,25,179,205,58,67,27,48,43,10,109,242,95,20,55,79,225, 53,109,109,81,194,69,228,133,181,118,98,94,126,198,244,76,66,233,166,55,237, 107,11,255,92,182,244,6,183,237,238,56,107,251,90,137,159,165,174,159,36,17, 124,75,31,230,73,40,102,81,236,228,91,61,194,0,124,184,161,99,191,5,152,218, 72,54,28,85,211,154,105,22,63,168,253,36,207,95,131,101,93,35,220,163,173, 150,28,98,243,86,32,133,82,187,158,213,41,7,112,150,150,109,103,12,53,78,74, 188,152,4,241,116,108,8,202,35,115,39,255,255,255,255,255,255,255,255]),
generator: new Uint8Array([2]),
};
// Alice gera sua chave...
window.crypto.subtle.generateKey(parametros, false, ["deriveKey", "deriveBits"])
.then(function(chaves){
var publica = chaves.publicKey;
var privada = chaves.privateKey;
// Serializa como string (base64)
window.crypto.subtle.exportKey("raw", publica).then(function(arraybuffer){
var publicaStr = btoa(String.fromCharCode.apply(null, new Uint8Array(arraybuffer)));
// ASSINA!!!
// ...
// E envia para Bob
// $.ajax(...)
document.body.innerHTML += "<p>Pública de Alice: <pre>" + publicaStr + "</pre></p>";
// Recebe a chave pública de Bob (gerada do mesmo jeito)
// $.ajax(...)
var bobStr = "i26tVhsmO6W8WnVu9xBROZOvFTP8n568eXZQtGR9/Ux+6RPOv4Dpkg2qVDP7gx1itY5vdC2r8KUxTfvHps3B9i6xQrlvc7CC3MY667GYp4HJge7M44dEsUTleH/xJTKITRWB7FGgfxJjQ7/z4yx5+KOD0DaLiIamPYL4XwZD3IDqbKYrngXhHNoexYAjrDskG3W0eZpy1fKJiDes9rs9ttTgSBezx+mUfBHpKUWuXzwdJhFJGnvTxW2hTna7gCER";
// VERIFICA A ASSINATURA!!!
// ...
// Deserializa e transforma numa chave
window.crypto.subtle.importKey("raw", _base64ToArrayBuffer(bobStr),
parametros, false, [])
.then(function(bob){
// Junta com os parâmetros
var parametrosMaisChave = Object.create(parametros, {
public:{ value: bob }
});
// Duas opções:
// 1. Deriva alguns bits comuns (mesmos derivados por Bob)
window.crypto.subtle.deriveBits(parametrosMaisChave, privada, 256)
.then(function(bits){
// Os bits comuns! :)
var bitsStr = btoa(String.fromCharCode.apply(null, new Uint8Array(bits)));
document.body.innerHTML += "<p>Bits comuns: <pre>" + bitsStr + "</pre></p>";
})
.catch(function(err){
document.body.innerHTML += "<p>Erro ao derivar bits:<pre>" + err + "</pre></p>";
});
// 2. Deriva uma chave comum (mesma derivada por Bob) para algum algoritmo
var parametrosChaveFinal = {
// o tipo de chave que você quer criar baseado nos bits derivados
name: "AES-CTR", // pode ser qualquer algoritmo AES ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
// Os parâmetros de geração para o tipo de algoritmo escolhido
length: 256, //pode ser 128, 192 ou 256
};
window.crypto.subtle.deriveKey(parametrosMaisChave, privada,
parametrosChaveFinal, false,
["encrypt", "decrypt"])
.then(function(key){
// A chave comum! :)
document.body.innerHTML += "<p>Combinação de chaves OK</p>";
})
.catch(function(err){
document.body.innerHTML += "<p>Erro ao combinar chaves:<pre>" + err + "</pre></p>";
});
})
.catch(function(err){
document.body.innerHTML += "<p>Erro ao importar chave:<pre>" + err + "</pre></p>";
});
})
.catch(function(err){
document.body.innerHTML += "<p>Erro ao exportar chave:<pre>" + err + "</pre></p>";
});
})
.catch(function(err){
document.body.innerHTML += "<p>Erro ao criar chave:<pre>" + err + "</pre></p>";
});
// http://stackoverflow.com/a/21797381/520779
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;
}