Lassen Sie uns eine vollständige elliptische Kurve tun Austausch Diffie-Hellman (ECDH) ein gemeinsames Geheimnis zwischen zwei Parteien herzustellen. Alice verwendet Node.js und Bob sitzt in seinem Browser (eine aktuelle Version von Chrome oder Firefox). (Keine Notwendigkeit, irgendetwas zu browserisieren.)
(1) Alice generiert einen privaten und öffentlichen Schlüssel.
const crypto = require('crypto');
const alice = crypto.createECDH('prime256v1');
alice.generateKeys()
const alicePublicKey = alice.getPublicKey('hex')
const alicePrivateKey = alice.getPrivateKey('hex')
console.log(`publicKey: ${alicePublicKey}`)
console.log(`privateKey: ${alicePrivateKey}`)
Beispiel Ausgabe:
publicKey: 043a3770a8068738ded16c9409e1a6fbf6dde2360ac5b3fd3e5bb8d9fd6adaed6ea83ff5153f58ae13098e86da89df1beb14ef46388d3df76e8fe2ee0ff9e926d5
privateKey: 03ce9cb317c8761699f174943dc9b2d2b7991515b48216a4c677fcf5ee879f2c
(2) Alice sendet ihren öffentlichen Schlüssel zu Bob (043a3770...
). Bob hat einige Helfer geschrieben, die Hex-Strings in Uint8Arrays
und Puffer in Hex-Strings konvertieren.
const hex2Arr = str => {
if (!str) {
return new Uint8Array()
}
const arr = []
for (let i = 0, len = str.length; i < len; i+=2) {
arr.push(parseInt(str.substr(i, 2), 16))
}
return new Uint8Array(arr)
}
const buf2Hex = buf => {
return Array.from(new Uint8Array(buf))
.map(x => ('00' + x.toString(16)).slice(-2))
.join('')
}
(3) Bob erhält Schlüssel des Alices und berechnet das Geheimnis geteilt
- Er erzeugt seine eigenen privaten und öffentlichen Schlüssel
- Er exportiert seinen öffentlichen Schlüssel und sendet sie an Alice
- Er Importiert Alices öffentlichen Schlüssel
Er berechnet das gemeinsame Geheimnis mit seinem privaten und Alices öffentlichen Schlüssel
// Alice's public key (received over an [insecure] connection)
const alicePublicKeyHex = '043a3770a8068738ded16c9409e1a6fbf6dde2360ac5b3fd3e5bb8d9fd6adaed6ea83ff5153f58ae13098e86da89df1beb14ef46388d3df76e8fe2ee0ff9e926d5'
const alicePublicKey = hex2Arr(alicePublicKeyHex)
console.log(`Alice's publicKey: ${alicePublicKeyHex}`)
let bob = null
// generate Bob's private and public key
window.crypto.subtle.generateKey(
{
name: 'ECDH',
namedCurve: 'P-256'
},
false, // no need to make Bob's private key exportable
['deriveKey', 'deriveBits'])
.then(bobKey => {
bob = bobKey
// export Bob's public key
return window.crypto.subtle.exportKey(
'raw', bobKey.publicKey
)
})
.then(bobPublicKeyExported => {
const bobPublicKeyHex = buf2Hex(bobPublicKeyExported)
// display and send Bob's public key to Alice
console.log(`Bob's publicKey: ${bobPublicKeyHex}`)
// import Alice's public key
return window.crypto.subtle.importKey(
'raw',
alicePublicKey,
{
name: 'ECDH',
namedCurve: 'P-256'
},
true,
[])
})
.then(aliceKeyImported => {
// use Alice's imported public key and
// Bob's private key to compute the shared secret
return window.crypto.subtle.deriveBits(
{
name: 'ECDH',
namedCurve: 'P-256',
public: aliceKeyImported
},
bob.privateKey,
256)
})
.then(sharedSecret => {
const sharedSecretHex = buf2Hex(sharedSecret)
console.log(`sharedSecret: ${sharedSecretHex}`)
})
.catch(err => {
console.log(err)
})
Beispiel Ausgang:
Alice's publicKey: 043a3770a8068738ded16c9409e1a6fbf6dde2360ac5b3fd3e5bb8d9fd6adaed6ea83ff5153f58ae13098e86da89df1beb14ef46388d3df76e8fe2ee0ff9e926d5
Bob's publicKey: 04aeceba6ae783c9b705833c2fa8822281f47f6f36bc867e4d398fa7a744d4fc63a010cbce1e6c9ac8858ad376a24ee8551615560f01c8bb63c86335c046b18962
sharedSecret: c26c9f370f001a947d7fec4dc9282d3e9ea718e1de487eb4f6fa7d6f0a311b97
(4) empfängt Alice Bob den öffentlichen Schlüssel (04aece...
). Sie berechnet auch das gemeinsame Geheimnis.
const crypto = require('crypto')
const alice = crypto.createECDH('prime256v1')
// Alice's privateKey (generated previously)
const alicePrivateKey = '937cdd11062b612ff3cb3e4a3c183254b9728b4c8c3a64de799ed196b672734b'
// Bob's publicKey transmitted to Alice
const bobPublicKey = '04aeceba6ae783c9b705833c2fa8822281f47f6f36bc867e4d398fa7a744d4fc63a010cbce1e6c9ac8858ad376a24ee8551615560f01c8bb63c86335c046b18962'
// set Alice's private key (not needed if continuing from (1))
alice.setPrivateKey(alicePrivateKey, 'hex')
const sharedSecret = alice.computeSecret(bobPublicKey, 'hex', 'hex')
console.log(`sharedSecret: ${sharedSecret}`)
examle output:
sharedSecret: c26c9f370f001a947d7fec4dc9282d3e9ea718e1de487eb4f6fa7d6f0a311b97
Die geheime gemeinsam benutzt wird (das gleiche).
(5) Das gemeinsame Geheimnis wird normalerweise verwendet, um einen symmetrischen Schlüssel für die Verschlüsselung von Nachrichten zwischen Alice und Bob abzuleiten (und sie haben glücklich miteinander kommuniziert).
Bemerkungen:
Normalerweise ist es nicht erforderlich oder privaten Schlüssel zu exportieren anzuzeigen. Alice würde typischerweise die Berechnung des gemeinsamen Geheimnisses von Schritt (1) fortsetzen (und alice.setPrivateKey(alicePrivateKey, 'hex')
weglassen).
Da das gemeinsame Geheimnis am häufigsten verwendet wird, um einen symmetrischen Schlüssel abzuleiten, können window.crypto.subtle.deriveKey
und deriveBits
weggelassen werden. deriveBits
wurde hier verwendet, um zu illustrieren, dass Alice und Bob tatsächlich einem gemeinsamen Geheimnis zustimmten.
Emh, danke ich denke ... erinnere mich nicht, was ich jetzt damit machen wollte. War vor 2 Jahren. – Endless