Created
January 2, 2023 23:30
-
-
Save foloinfo/ed3733393ec859c0c8fb510b7baf6355 to your computer and use it in GitHub Desktop.
Deno compatible encryption with x25519-xsalsa20-poly1305 for Metamask (using eth_getEncryptionPublicKey and eth_decrypt)
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 * as nacl from 'https://raw.githubusercontent.com/intob/tweetnacl-deno/master/src/nacl.ts' | |
export function hex(arrayBuffer) | |
{ | |
return Array.prototype.map.call( | |
new Uint8Array(arrayBuffer), | |
n => n.toString(16).padStart(2, "0") | |
).join(""); | |
} | |
// slightly modified from | |
// https://github.com/MetaMask/eth-sig-util/blob/main/src/encryption.ts | |
export function isNullish(value: any) { | |
return value === null || value === undefined; | |
} | |
export interface EthEncryptedData { | |
version: string; | |
nonce: string; | |
ephemPublicKey: string; | |
ciphertext: string; | |
} | |
/** | |
* Encrypt a message. | |
* | |
* @param options - The encryption options. | |
* @param options.publicKey - The public key of the message recipient. | |
* @param options.data - The message data. | |
* @param options.version - The type of encryption to use. | |
* @returns The encrypted data. | |
*/ | |
export function encrypt({ | |
publicKey, | |
data, | |
version, | |
}: { | |
publicKey: string; | |
data: unknown; | |
version: string; | |
}): EthEncryptedData { | |
if (isNullish(publicKey)) { | |
throw new Error('Missing publicKey parameter'); | |
} else if (isNullish(data)) { | |
throw new Error('Missing data parameter'); | |
} else if (isNullish(version)) { | |
throw new Error('Missing version parameter'); | |
} | |
switch (version) { | |
case 'x25519-xsalsa20-poly1305': { | |
if (typeof data !== 'string') { | |
throw new Error('Message data must be given as a string'); | |
} | |
// generate ephemeral keypair | |
const ephemeralKeyPair = nacl.box_keyPair(); | |
// assemble encryption parameters - from string to UInt8 | |
let pubKeyUInt8Array; | |
try { | |
pubKeyUInt8Array = nacl.decodeBase64(publicKey); | |
} catch (err) { | |
throw new Error('Bad public key'); | |
} | |
const msgParamsUInt8Array = nacl.decodeUTF8(data); | |
const nonce = nacl.randomBytes(24); | |
// encrypt | |
const encryptedMessage = nacl.box( | |
msgParamsUInt8Array, | |
nonce, | |
pubKeyUInt8Array, | |
ephemeralKeyPair.secretKey, | |
); | |
// handle encrypted data | |
const output = { | |
version: 'x25519-xsalsa20-poly1305', | |
nonce: nacl.encodeBase64(nonce), | |
ephemPublicKey: nacl.encodeBase64(ephemeralKeyPair.publicKey), | |
ciphertext: nacl.encodeBase64(encryptedMessage), | |
}; | |
// return encrypted msg data | |
return output; | |
} | |
default: | |
throw new Error('Encryption type/version not supported'); | |
} | |
} |
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 { encrypt, hex } from './eth_encrypt.ts' | |
const publicKey = 'public key generated by eth_getEncryptionPublicKey' | |
const data = 'whatever you want to encrypt' | |
const encrypted = encrypt({ | |
publicKey, | |
data, | |
version: 'x25519-xsalsa20-poly1305', | |
}) | |
const encoder = new TextEncoder() | |
const encryptedMessage = hex( | |
encoder.encode( | |
JSON.stringify(encrypted) | |
) | |
) | |
// you can pass this encryptedString to eth_decrypt to read on client | |
// https://docs.metamask.io/guide/rpc-api.html#unrestricted-methods | |
// ethereum | |
// .request({ | |
// method: 'eth_decrypt', | |
// params: [encryptedMessage, accounts[0]], | |
// }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment