Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 41x 41x 41x 41x 41x 41x 41x 25x 25x 25x 22x 22x 22x 22x 22x 22x 22x 20x 2x 2x 22x 22x 2x 22x | import { getPublicKey, getSharedSecret, utils } from '@noble/secp256k1';
import { bytesToHex, bytesToBase64, concatByteArrays } from 'micro-stacks/common';
import { getRandomBytes } from '../common/random-bytes';
import type { CipherObject, EncryptECIESOptions } from '../common/types';
import { aes256CbcEncrypt } from 'micro-stacks/crypto-aes';
import { sharedSecretToKeys } from '../common/shared-secret';
import { hmacSha256 } from 'micro-stacks/crypto-hmac-sha';
/**
* Encrypt content to elliptic curve publicKey using ECIES
* @return Object containing:
* iv (initialization vector, hex encoding),
* cipherText (cipher text either hex or base64 encoded),
* mac (message authentication code, hex encoded),
* ephemeral public key (hex encoded),
* wasString (boolean indicating with or not to return a buffer or string on decrypt)
* @see https://cryptobook.nakov.com/asymmetric-key-ciphers/ecies-public-key-encryption
*/
export async function encryptECIES(options: EncryptECIESOptions): Promise<CipherObject> {
const { publicKey, content, cipherTextEncoding = 'hex', wasString } = options;
const ephemeralPrivateKey = utils.randomPrivateKey();
const ephemeralPublicKey = getPublicKey(ephemeralPrivateKey, true);
let sharedSecret = getSharedSecret(ephemeralPrivateKey, publicKey, true) as Uint8Array;
// Trim the compressed mode prefix byte
sharedSecret = sharedSecret.slice(1);
const sharedKeys = sharedSecretToKeys(sharedSecret);
const initializationVector = getRandomBytes(16);
const cipherText = await aes256CbcEncrypt(
initializationVector,
sharedKeys.encryptionKey,
content
);
const macData = concatByteArrays([initializationVector, ephemeralPublicKey, cipherText]);
const mac = hmacSha256(sharedKeys.hmacKey, macData);
let cipherTextString: string;
if (!cipherTextEncoding || cipherTextEncoding === 'hex') {
cipherTextString = bytesToHex(cipherText);
} else if (cipherTextEncoding === 'base64') {
cipherTextString = bytesToBase64(cipherText);
} else E{
throw new Error(`Unexpected cipherTextEncoding "${cipherTextEncoding}"`);
}
const result: CipherObject = {
iv: bytesToHex(initializationVector),
ephemeralPK: bytesToHex(ephemeralPublicKey),
cipherText: cipherTextString,
mac: bytesToHex(mac),
wasString,
};
if (cipherTextEncoding && cipherTextEncoding !== 'hex') {
result.cipherTextEncoding = cipherTextEncoding;
}
return result;
}
|