Created
September 30, 2022 19:35
-
-
Save OR13/7d99f46c56e7f78082097452158125ef to your computer and use it in GitHub Desktop.
opacity: 1;
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import crypto from 'crypto' | |
import assert from 'assert'; | |
import { Kem, Kdf, Aead, CipherSuite } from 'hpke-js' | |
const suite = new CipherSuite({ | |
kem: Kem.DhkemP256HkdfSha256, | |
kdf: Kdf.HkdfSha256, | |
aead: Aead.Aes128Gcm | |
}); | |
const encryptMessage = async (publicKeyJwk, message)=> { | |
const importedPublicKey = await crypto.subtle.importKey('jwk', {...publicKeyJwk, key_ops: ['deriveBits']}, { | |
name: "ECDH", | |
namedCurve: "P-256" | |
}, true, ['deriveBits']) | |
const sender = await suite.createSenderContext({ | |
recipientPublicKey: importedPublicKey | |
}); | |
const ct = await sender.seal(message); | |
const encodedSender = Buffer.from(sender.enc).toString('hex') | |
let epk = { | |
kty: publicKeyJwk.kty, | |
crv: publicKeyJwk.crv, | |
key_ops: ['deriveBits'], | |
x: Buffer.from(encodedSender.slice(2, 66), 'hex').toString('base64'), | |
y: Buffer.from(encodedSender.slice(66), 'hex').toString('base64') | |
} | |
const encRaw = Uint8Array.from(Buffer.from(encodedSender, 'hex')); | |
const encJwk = JSON.stringify(epk) | |
const encCwk = undefined; | |
const encMultibase = undefined; | |
const encPem = undefined; | |
const encHex = undefined; | |
const encBase64 = undefined; | |
const encBase58 = undefined; | |
return { ct, encRaw, encJwk, encCwk, encMultibase, encPem, encHex, encBase64, encBase58 } | |
} | |
// sniff encAny, and transform to format expected by the underlying HPKE library | |
// In the case of dajiaji/hpke-js -> 04 + hex(x) + hex(y) | |
// In the case of ... -> ... | |
const decryptMessage = async (privateKeyJwk, encAny, ct) =>{ | |
const importedPrivateKey = await crypto.subtle.importKey('jwk', {...privateKeyJwk, key_ops: ['deriveBits']}, { | |
name: "ECDH", | |
namedCurve: "P-256" | |
}, true, ['deriveBits']) | |
let decodedSender = undefined; | |
if (typeof encAny === 'string'){ | |
const publicKeyJwk = JSON.parse(encAny) | |
const buffer = Buffer.concat([Buffer.from('04', 'hex'), Buffer.from(publicKeyJwk.x, 'base64'), Buffer.from(publicKeyJwk.y, 'base64')]) | |
decodedSender = Uint8Array.from(buffer) | |
} else { | |
decodedSender = encAny | |
} | |
const recipient = await suite.createRecipientContext({ | |
recipientKey: importedPrivateKey, | |
enc: decodedSender, | |
}); | |
const pt = await recipient.open(ct); | |
return pt | |
} | |
(async ()=>{ | |
const rkp = await suite.generateKeyPair(); | |
const publicKeyJwk = await crypto.subtle.exportKey('jwk', rkp.publicKey ) | |
const privateKeyJwk = await crypto.subtle.exportKey('jwk', rkp.privateKey ) | |
const message = new TextEncoder().encode("hello world!"); | |
const { ct, encRaw, encJwk } = await encryptMessage(publicKeyJwk, message) | |
const pt1 = await decryptMessage(privateKeyJwk, encRaw, ct) | |
assert(new TextDecoder().decode(pt1) === 'hello world!', 'Failed to decrypt message.') | |
const pt2 = await decryptMessage(privateKeyJwk, encJwk, ct) | |
assert(new TextDecoder().decode(pt2) === 'hello world!', 'Failed to decrypt message.') | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment