+22
-4
@@ -0,2 +1,20 @@ | ||
| /** | ||
| * Encrypts a message. | ||
| * @description From version 0.5.0, `Uint8Array` will be returned instead of `Buffer`. | ||
| * To keep the same behavior, use `Buffer.from(encrypt(...))`. | ||
| * | ||
| * @param receiverRawPK - Raw public key of the receiver, either as a hex string or a Uint8Array. | ||
| * @param msg - Message to encrypt. | ||
| * @returns Encrypted payload, format: `public key || encrypted`. | ||
| */ | ||
| export declare function encrypt(receiverRawPK: string | Uint8Array, msg: Uint8Array): Buffer; | ||
| /** | ||
| * Decrypts a message. | ||
| * @description From version 0.5.0, `Uint8Array` will be returned instead of `Buffer`. | ||
| * To keep the same behavior, use `Buffer.from(decrypt(...))`. | ||
| * | ||
| * @param receiverRawSK - Raw private key of the receiver, either as a hex string or a Uint8Array. | ||
| * @param msg - Message to decrypt. | ||
| * @returns Decrypted plain text. | ||
| */ | ||
| export declare function decrypt(receiverRawSK: string | Uint8Array, msg: Uint8Array): Buffer; | ||
@@ -7,6 +25,6 @@ export { ECIES_CONFIG } from "./config"; | ||
| export declare const utils: { | ||
| aesEncrypt: (key: Uint8Array, plainText: Uint8Array) => Uint8Array; | ||
| aesDecrypt: (key: Uint8Array, cipherText: Uint8Array) => Uint8Array; | ||
| symEncrypt: (key: Uint8Array, plainText: Uint8Array) => Uint8Array; | ||
| symDecrypt: (key: Uint8Array, cipherText: Uint8Array) => Uint8Array; | ||
| aesEncrypt: (key: Uint8Array, plainText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| aesDecrypt: (key: Uint8Array, cipherText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| symEncrypt: (key: Uint8Array, plainText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| symDecrypt: (key: Uint8Array, cipherText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| decodeHex: (hex: string) => Uint8Array; | ||
@@ -13,0 +31,0 @@ getValidSecret: () => Uint8Array; |
+29
-15
@@ -10,18 +10,32 @@ "use strict"; | ||
| var utils_2 = require("./utils"); | ||
| /** | ||
| * Encrypts a message. | ||
| * @description From version 0.5.0, `Uint8Array` will be returned instead of `Buffer`. | ||
| * To keep the same behavior, use `Buffer.from(encrypt(...))`. | ||
| * | ||
| * @param receiverRawPK - Raw public key of the receiver, either as a hex string or a Uint8Array. | ||
| * @param msg - Message to encrypt. | ||
| * @returns Encrypted payload, format: `public key || encrypted`. | ||
| */ | ||
| function encrypt(receiverRawPK, msg) { | ||
| var ephemeralKey = new keys_1.PrivateKey(); | ||
| var ephemeralSK = new keys_1.PrivateKey(); | ||
| var receiverPK = receiverRawPK instanceof Uint8Array | ||
| ? new keys_1.PublicKey(receiverRawPK) | ||
| : keys_1.PublicKey.fromHex(receiverRawPK); | ||
| var symKey = ephemeralKey.encapsulate(receiverPK); | ||
| var encrypted = (0, utils_2.symEncrypt)(symKey, msg); | ||
| var pk; | ||
| if ((0, config_1.isEphemeralKeyCompressed)()) { | ||
| pk = ephemeralKey.publicKey.compressed; | ||
| } | ||
| else { | ||
| pk = ephemeralKey.publicKey.uncompressed; | ||
| } | ||
| return Buffer.from((0, utils_1.concatBytes)(pk, encrypted)); | ||
| var sharedKey = ephemeralSK.encapsulate(receiverPK, (0, config_1.isHkdfKeyCompressed)()); | ||
| var ephemeralPK = (0, config_1.isEphemeralKeyCompressed)() | ||
| ? ephemeralSK.publicKey.compressed | ||
| : ephemeralSK.publicKey.uncompressed; | ||
| var encrypted = (0, utils_2.symEncrypt)(sharedKey, msg); | ||
| return Buffer.from((0, utils_1.concatBytes)(ephemeralPK, encrypted)); | ||
| } | ||
| /** | ||
| * Decrypts a message. | ||
| * @description From version 0.5.0, `Uint8Array` will be returned instead of `Buffer`. | ||
| * To keep the same behavior, use `Buffer.from(decrypt(...))`. | ||
| * | ||
| * @param receiverRawSK - Raw private key of the receiver, either as a hex string or a Uint8Array. | ||
| * @param msg - Message to decrypt. | ||
| * @returns Decrypted plain text. | ||
| */ | ||
| function decrypt(receiverRawSK, msg) { | ||
@@ -32,6 +46,6 @@ var receiverSK = receiverRawSK instanceof Uint8Array | ||
| var keySize = (0, config_1.ephemeralKeySize)(); | ||
| var senderPK = new keys_1.PublicKey(msg.subarray(0, keySize)); | ||
| var ephemeralPK = new keys_1.PublicKey(msg.subarray(0, keySize)); | ||
| var encrypted = msg.subarray(keySize); | ||
| var symKey = senderPK.decapsulate(receiverSK); | ||
| return Buffer.from((0, utils_2.symDecrypt)(symKey, encrypted)); | ||
| var sharedKey = ephemeralPK.decapsulate(receiverSK, (0, config_1.isHkdfKeyCompressed)()); | ||
| return Buffer.from((0, utils_2.symDecrypt)(sharedKey, encrypted)); | ||
| } | ||
@@ -45,3 +59,3 @@ var config_2 = require("./config"); | ||
| exports.utils = { | ||
| // TODO: review these before 0.5.0 | ||
| // TODO: remove these after 0.5.0 | ||
| aesEncrypt: utils_2.aesEncrypt, | ||
@@ -48,0 +62,0 @@ aesDecrypt: utils_2.aesDecrypt, |
@@ -9,5 +9,20 @@ import { PublicKey } from "./PublicKey"; | ||
| toHex(): string; | ||
| encapsulate(pk: PublicKey): Uint8Array; | ||
| /** | ||
| * Derives a shared secret from ephemeral private key (this) and receiver's public key (pk). | ||
| * @description The shared key is 32 bytes, derived with `HKDF-SHA256(senderPoint || sharedPoint)`. See implementation for details. | ||
| * | ||
| * There are some variations in different ECIES implementations: | ||
| * which key derivation function to use, compressed or uncompressed `senderPoint`/`sharedPoint`, whether to include `senderPoint`, etc. | ||
| * | ||
| * Because the entropy of `senderPoint`, `sharedPoint` is enough high[1], we don't need salt to derive keys. | ||
| * | ||
| * [1]: Two reasons: the public keys are "random" bytes (albeit secp256k1 public keys are **not uniformly** random), and ephemeral keys are generated in every encryption. | ||
| * | ||
| * @param pk - Receiver's public key. | ||
| * @param compressed - Whether to use compressed or uncompressed public keys in the key derivation (secp256k1 only). | ||
| * @returns Shared secret, derived with HKDF-SHA256. | ||
| */ | ||
| encapsulate(pk: PublicKey, compressed?: boolean): Uint8Array; | ||
| multiply(pk: PublicKey, compressed?: boolean): Uint8Array; | ||
| equals(other: PrivateKey): boolean; | ||
| } |
+29
-16
@@ -5,3 +5,2 @@ "use strict"; | ||
| var utils_1 = require("@noble/ciphers/utils"); | ||
| var config_1 = require("../config"); | ||
| var utils_2 = require("../utils"); | ||
@@ -11,8 +10,12 @@ var PublicKey_1 = require("./PublicKey"); | ||
| function PrivateKey(secret) { | ||
| var sk = secret === undefined ? (0, utils_2.getValidSecret)() : secret; | ||
| if (!(0, utils_2.isValidPrivateKey)(sk)) { | ||
| if (secret === undefined) { | ||
| this.data = (0, utils_2.getValidSecret)(); | ||
| } | ||
| else if ((0, utils_2.isValidPrivateKey)(secret)) { | ||
| this.data = secret; | ||
| } | ||
| else { | ||
| throw new Error("Invalid private key"); | ||
| } | ||
| this.data = sk; | ||
| this.publicKey = new PublicKey_1.PublicKey((0, utils_2.getPublicKey)(sk)); | ||
| this.publicKey = new PublicKey_1.PublicKey((0, utils_2.getPublicKey)(this.data)); | ||
| } | ||
@@ -33,13 +36,23 @@ PrivateKey.fromHex = function (hex) { | ||
| }; | ||
| PrivateKey.prototype.encapsulate = function (pk) { | ||
| var senderPoint; | ||
| var sharedPoint; | ||
| if ((0, config_1.isHkdfKeyCompressed)()) { | ||
| senderPoint = this.publicKey.compressed; | ||
| sharedPoint = this.multiply(pk, true); | ||
| } | ||
| else { | ||
| senderPoint = this.publicKey.uncompressed; | ||
| sharedPoint = this.multiply(pk, false); | ||
| } | ||
| /** | ||
| * Derives a shared secret from ephemeral private key (this) and receiver's public key (pk). | ||
| * @description The shared key is 32 bytes, derived with `HKDF-SHA256(senderPoint || sharedPoint)`. See implementation for details. | ||
| * | ||
| * There are some variations in different ECIES implementations: | ||
| * which key derivation function to use, compressed or uncompressed `senderPoint`/`sharedPoint`, whether to include `senderPoint`, etc. | ||
| * | ||
| * Because the entropy of `senderPoint`, `sharedPoint` is enough high[1], we don't need salt to derive keys. | ||
| * | ||
| * [1]: Two reasons: the public keys are "random" bytes (albeit secp256k1 public keys are **not uniformly** random), and ephemeral keys are generated in every encryption. | ||
| * | ||
| * @param pk - Receiver's public key. | ||
| * @param compressed - Whether to use compressed or uncompressed public keys in the key derivation (secp256k1 only). | ||
| * @returns Shared secret, derived with HKDF-SHA256. | ||
| */ | ||
| PrivateKey.prototype.encapsulate = function (pk, compressed) { | ||
| if (compressed === void 0) { compressed = false; } | ||
| var senderPoint = compressed | ||
| ? this.publicKey.compressed | ||
| : this.publicKey.uncompressed; | ||
| var sharedPoint = this.multiply(pk, compressed); | ||
| return (0, utils_2.getSharedKey)(senderPoint, sharedPoint); | ||
@@ -46,0 +59,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
| import { PrivateKey } from "./PrivateKey"; | ||
| import type { PrivateKey } from "./PrivateKey"; | ||
| export declare class PublicKey { | ||
@@ -9,4 +9,13 @@ static fromHex(hex: string): PublicKey; | ||
| toHex(compressed?: boolean): string; | ||
| decapsulate(sk: PrivateKey): Uint8Array; | ||
| /** | ||
| * Derives a shared secret from receiver's private key (sk) and ephemeral public key (this). | ||
| * Opposite of `encapsulate`. | ||
| * @see PrivateKey.encapsulate | ||
| * | ||
| * @param sk - Receiver's private key. | ||
| * @param compressed - Whether to use compressed or uncompressed public keys in the key derivation (secp256k1 only). | ||
| * @returns Shared secret, derived with HKDF-SHA256. | ||
| */ | ||
| decapsulate(sk: PrivateKey, compressed?: boolean): Uint8Array; | ||
| equals(other: PublicKey): boolean; | ||
| } |
+13
-12
@@ -5,3 +5,2 @@ "use strict"; | ||
| var utils_1 = require("@noble/ciphers/utils"); | ||
| var config_1 = require("../config"); | ||
| var utils_2 = require("../utils"); | ||
@@ -40,13 +39,15 @@ var PublicKey = /** @class */ (function () { | ||
| }; | ||
| PublicKey.prototype.decapsulate = function (sk) { | ||
| var senderPoint; | ||
| var sharedPoint; | ||
| if ((0, config_1.isHkdfKeyCompressed)()) { | ||
| senderPoint = this.data; | ||
| sharedPoint = sk.multiply(this, true); | ||
| } | ||
| else { | ||
| senderPoint = this.uncompressed; | ||
| sharedPoint = sk.multiply(this, false); | ||
| } | ||
| /** | ||
| * Derives a shared secret from receiver's private key (sk) and ephemeral public key (this). | ||
| * Opposite of `encapsulate`. | ||
| * @see PrivateKey.encapsulate | ||
| * | ||
| * @param sk - Receiver's private key. | ||
| * @param compressed - Whether to use compressed or uncompressed public keys in the key derivation (secp256k1 only). | ||
| * @returns Shared secret, derived with HKDF-SHA256. | ||
| */ | ||
| PublicKey.prototype.decapsulate = function (sk, compressed) { | ||
| if (compressed === void 0) { compressed = false; } | ||
| var senderPoint = compressed ? this.data : this.uncompressed; | ||
| var sharedPoint = sk.multiply(this, compressed); | ||
| return (0, utils_2.getSharedKey)(senderPoint, sharedPoint); | ||
@@ -53,0 +54,0 @@ }; |
@@ -0,7 +1,6 @@ | ||
| export declare const getValidSecret: () => Uint8Array; | ||
| export declare const isValidPrivateKey: (secret: Uint8Array) => boolean; | ||
| export declare const getValidSecret: () => Uint8Array; | ||
| export declare const getPublicKey: (secret: Uint8Array) => Uint8Array; | ||
| export declare const getSharedKey: (ephemeralPoint: Uint8Array, sharedPoint: Uint8Array) => Uint8Array; | ||
| export declare const getSharedPoint: (sk: Uint8Array, pk: Uint8Array, compressed?: boolean) => Uint8Array; | ||
| export declare const convertPublicKeyFormat: (pk: Uint8Array, compressed: boolean) => Uint8Array; | ||
| export declare const hexToPublicKey: (hex: string) => Uint8Array; |
+27
-30
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.hexToPublicKey = exports.convertPublicKeyFormat = exports.getSharedPoint = exports.getSharedKey = exports.getPublicKey = exports.getValidSecret = exports.isValidPrivateKey = void 0; | ||
| var utils_1 = require("@noble/ciphers/utils"); | ||
| exports.hexToPublicKey = exports.convertPublicKeyFormat = exports.getSharedPoint = exports.getPublicKey = exports.isValidPrivateKey = exports.getValidSecret = void 0; | ||
| var webcrypto_1 = require("@noble/ciphers/webcrypto"); | ||
@@ -10,10 +9,3 @@ var ed25519_1 = require("@noble/curves/ed25519"); | ||
| var consts_1 = require("../consts"); | ||
| var hash_1 = require("./hash"); | ||
| var hex_1 = require("./hex"); | ||
| var isValidPrivateKey = function (secret) { | ||
| // on secp256k1: only key ∈ (0, group order) is valid | ||
| // on curve25519: any 32-byte key is valid | ||
| return _exec(function (curve) { return curve.utils.isValidPrivateKey(secret); }, function () { return true; }, function () { return true; }); | ||
| }; | ||
| exports.isValidPrivateKey = isValidPrivateKey; | ||
| var getValidSecret = function () { | ||
@@ -27,15 +19,14 @@ var key; | ||
| exports.getValidSecret = getValidSecret; | ||
| var isValidPrivateKey = function (secret) { | ||
| // on secp256k1: only key ∈ (0, group order) is valid | ||
| // on curve25519: any 32-byte key is valid | ||
| return _exec((0, config_1.ellipticCurve)(), function (curve) { return curve.utils.isValidPrivateKey(secret); }, function () { return true; }, function () { return true; }); | ||
| }; | ||
| exports.isValidPrivateKey = isValidPrivateKey; | ||
| var getPublicKey = function (secret) { | ||
| return _exec(function (curve) { return curve.getPublicKey(secret); }, function (curve) { return curve.getPublicKey(secret); }, function (curve) { return curve.getPublicKey(secret); }); | ||
| return _exec((0, config_1.ellipticCurve)(), function (curve) { return curve.getPublicKey(secret); }, function (curve) { return curve.getPublicKey(secret); }, function (curve) { return curve.getPublicKey(secret); }); | ||
| }; | ||
| exports.getPublicKey = getPublicKey; | ||
| var getSharedKey = function (ephemeralPoint, sharedPoint) { return (0, hash_1.deriveKey)((0, utils_1.concatBytes)(ephemeralPoint, sharedPoint)); }; | ||
| exports.getSharedKey = getSharedKey; | ||
| var getSharedPoint = function (sk, pk, compressed) { | ||
| return _exec(function (curve) { return curve.getSharedSecret(sk, pk, compressed); }, function (curve) { return curve.getSharedSecret(sk, pk); }, function (curve) { | ||
| // Note: scalar is hashed from sk | ||
| var scalar = curve.utils.getExtendedPublicKey(sk).scalar; | ||
| var point = curve.ExtendedPoint.fromHex(pk).multiply(scalar); | ||
| return point.toRawBytes(); | ||
| }); | ||
| return _exec((0, config_1.ellipticCurve)(), function (curve) { return curve.getSharedSecret(sk, pk, compressed); }, function (curve) { return curve.getSharedSecret(sk, pk); }, function (curve) { return getSharedPointOnEd25519(curve, sk, pk); }); | ||
| }; | ||
@@ -45,3 +36,3 @@ exports.getSharedPoint = getSharedPoint; | ||
| // only for secp256k1 | ||
| return _exec(function (curve) { return curve.getSharedSecret(BigInt(1), pk, compressed); }, function () { return pk; }, function () { return pk; }); | ||
| return _exec((0, config_1.ellipticCurve)(), function (curve) { return curve.getSharedSecret(BigInt(1), pk, compressed); }, function () { return pk; }, function () { return pk; }); | ||
| }; | ||
@@ -51,15 +42,6 @@ exports.convertPublicKeyFormat = convertPublicKeyFormat; | ||
| var decoded = (0, hex_1.decodeHex)(hex); | ||
| return _exec(function () { | ||
| if (decoded.length === consts_1.ETH_PUBLIC_KEY_SIZE) { | ||
| var fixed = new Uint8Array(1 + decoded.length); | ||
| fixed.set([0x04]); | ||
| fixed.set(decoded, 1); | ||
| return fixed; | ||
| } | ||
| return decoded; | ||
| }, function () { return decoded; }, function () { return decoded; }); | ||
| return _exec((0, config_1.ellipticCurve)(), function () { return compatEthPublicKey(decoded); }, function () { return decoded; }, function () { return decoded; }); | ||
| }; | ||
| exports.hexToPublicKey = hexToPublicKey; | ||
| function _exec(secp256k1Callback, x25519Callback, ed25519Callback) { | ||
| var curve = (0, config_1.ellipticCurve)(); | ||
| function _exec(curve, secp256k1Callback, x25519Callback, ed25519Callback) { | ||
| if (curve === "secp256k1") { | ||
@@ -78,1 +60,16 @@ return secp256k1Callback(secp256k1_1.secp256k1); | ||
| } | ||
| var compatEthPublicKey = function (pk) { | ||
| if (pk.length === consts_1.ETH_PUBLIC_KEY_SIZE) { | ||
| var fixed = new Uint8Array(1 + pk.length); | ||
| fixed.set([0x04]); | ||
| fixed.set(pk, 1); | ||
| return fixed; | ||
| } | ||
| return pk; | ||
| }; | ||
| var getSharedPointOnEd25519 = function (curve, sk, pk) { | ||
| // Note: scalar is hashed from sk | ||
| var scalar = curve.utils.getExtendedPublicKey(sk).scalar; | ||
| var point = curve.ExtendedPoint.fromHex(pk).multiply(scalar); | ||
| return point.toRawBytes(); | ||
| }; |
@@ -1,1 +0,2 @@ | ||
| export declare const deriveKey: (master: Uint8Array) => Uint8Array; | ||
| export declare const deriveKey: (master: Uint8Array, salt?: Uint8Array, info?: Uint8Array) => Uint8Array; | ||
| export declare const getSharedKey: (...parts: Uint8Array[]) => Uint8Array; |
+12
-3
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.deriveKey = void 0; | ||
| exports.getSharedKey = exports.deriveKey = void 0; | ||
| var utils_1 = require("@noble/ciphers/utils"); | ||
| var hkdf_1 = require("@noble/hashes/hkdf"); | ||
| var sha256_1 = require("@noble/hashes/sha256"); | ||
| var deriveKey = function (master) { | ||
| var deriveKey = function (master, salt, info) { | ||
| // 32 bytes shared secret for aes256 and xchacha20 derived from HKDF-SHA256 | ||
| return (0, hkdf_1.hkdf)(sha256_1.sha256, master, undefined, undefined, 32); | ||
| return (0, hkdf_1.hkdf)(sha256_1.sha256, master, salt, info, 32); | ||
| }; | ||
| exports.deriveKey = deriveKey; | ||
| var getSharedKey = function () { | ||
| var parts = []; | ||
| for (var _i = 0; _i < arguments.length; _i++) { | ||
| parts[_i] = arguments[_i]; | ||
| } | ||
| return (0, exports.deriveKey)(utils_1.concatBytes.apply(void 0, parts)); | ||
| }; | ||
| exports.getSharedKey = getSharedKey; |
@@ -17,3 +17,2 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| // under this folder no `Buffer` | ||
| __exportStar(require("./elliptic"), exports); | ||
@@ -20,0 +19,0 @@ __exportStar(require("./hash"), exports); |
@@ -1,6 +0,6 @@ | ||
| export declare const symEncrypt: (key: Uint8Array, plainText: Uint8Array) => Uint8Array; | ||
| export declare const symDecrypt: (key: Uint8Array, cipherText: Uint8Array) => Uint8Array; | ||
| export declare const symEncrypt: (key: Uint8Array, plainText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| export declare const symDecrypt: (key: Uint8Array, cipherText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| /** @deprecated - use `symEncrypt` instead. */ | ||
| export declare const aesEncrypt: (key: Uint8Array, plainText: Uint8Array) => Uint8Array; | ||
| export declare const aesEncrypt: (key: Uint8Array, plainText: Uint8Array, AAD?: Uint8Array) => Uint8Array; | ||
| /** @deprecated - use `symDecrypt` instead. */ | ||
| export declare const aesDecrypt: (key: Uint8Array, cipherText: Uint8Array) => Uint8Array; | ||
| export declare const aesDecrypt: (key: Uint8Array, cipherText: Uint8Array, AAD?: Uint8Array) => Uint8Array; |
+27
-23
@@ -10,9 +10,5 @@ "use strict"; | ||
| var consts_1 = require("../consts"); | ||
| var symEncrypt = function (key, plainText) { | ||
| return _exec(_encrypt, key, plainText); | ||
| }; | ||
| var symEncrypt = function (key, plainText, AAD) { return _exec(_encrypt, key, plainText, AAD); }; | ||
| exports.symEncrypt = symEncrypt; | ||
| var symDecrypt = function (key, cipherText) { | ||
| return _exec(_decrypt, key, cipherText); | ||
| }; | ||
| var symDecrypt = function (key, cipherText, AAD) { return _exec(_decrypt, key, cipherText, AAD); }; | ||
| exports.symDecrypt = symDecrypt; | ||
@@ -23,9 +19,9 @@ /** @deprecated - use `symEncrypt` instead. */ | ||
| exports.aesDecrypt = exports.symDecrypt; // TODO: delete | ||
| function _exec(callback, key, data) { | ||
| function _exec(callback, key, data, AAD) { | ||
| var algorithm = (0, config_1.symmetricAlgorithm)(); | ||
| if (algorithm === "aes-256-gcm") { | ||
| return callback(aes_1.aes256gcm, key, data, (0, config_1.symmetricNonceLength)(), consts_1.AEAD_TAG_LENGTH); | ||
| return callback(aes_1.aes256gcm, key, data, (0, config_1.symmetricNonceLength)(), consts_1.AEAD_TAG_LENGTH, AAD); | ||
| } | ||
| else if (algorithm === "xchacha20") { | ||
| return callback(chacha_1.xchacha20, key, data, consts_1.XCHACHA20_NONCE_LENGTH, consts_1.AEAD_TAG_LENGTH); | ||
| return callback(chacha_1.xchacha20, key, data, consts_1.XCHACHA20_NONCE_LENGTH, consts_1.AEAD_TAG_LENGTH, AAD); | ||
| } | ||
@@ -41,18 +37,26 @@ else if (algorithm === "aes-256-cbc") { | ||
| } | ||
| function _encrypt(func, key, plainText, nonceLength, tagLength) { | ||
| function _encrypt(func, key, data, nonceLength, tagLength, AAD) { | ||
| var nonce = (0, webcrypto_1.randomBytes)(nonceLength); | ||
| var cipher = func(key, nonce); | ||
| var ciphered = cipher.encrypt(plainText); // encrypted || tag | ||
| var encrypted = ciphered.subarray(0, ciphered.length - tagLength); | ||
| var tag = ciphered.subarray(ciphered.length - tagLength); | ||
| return (0, utils_1.concatBytes)(nonce, tag, encrypted); | ||
| var cipher = func(key, nonce, AAD); | ||
| // @noble/ciphers format: cipherText || tag | ||
| var encrypted = cipher.encrypt(data); | ||
| if (tagLength === 0) { | ||
| return (0, utils_1.concatBytes)(nonce, encrypted); | ||
| } | ||
| var cipherTextLength = encrypted.length - tagLength; | ||
| var cipherText = encrypted.subarray(0, cipherTextLength); | ||
| var tag = encrypted.subarray(cipherTextLength); | ||
| // ecies payload format: pk || nonce || tag || cipherText | ||
| return (0, utils_1.concatBytes)(nonce, tag, cipherText); | ||
| } | ||
| function _decrypt(func, key, cipherText, nonceLength, tagLength) { | ||
| var nonceTagLength = nonceLength + tagLength; | ||
| var nonce = cipherText.subarray(0, nonceLength); | ||
| var tag = cipherText.subarray(nonceLength, nonceTagLength); | ||
| var encrypted = cipherText.subarray(nonceTagLength); | ||
| var decipher = func(key, Uint8Array.from(nonce)); // to reset byteOffset | ||
| var ciphered = (0, utils_1.concatBytes)(encrypted, tag); | ||
| return decipher.decrypt(ciphered); | ||
| function _decrypt(func, key, data, nonceLength, tagLength, AAD) { | ||
| var nonce = data.subarray(0, nonceLength); | ||
| var cipher = func(key, Uint8Array.from(nonce), AAD); // to reset byteOffset | ||
| var encrypted = data.subarray(nonceLength); | ||
| if (tagLength === 0) { | ||
| return cipher.decrypt(encrypted); | ||
| } | ||
| var tag = encrypted.subarray(0, tagLength); | ||
| var cipherText = encrypted.subarray(tagLength); | ||
| return cipher.decrypt((0, utils_1.concatBytes)(cipherText, tag)); | ||
| } |
+15
-16
@@ -14,5 +14,7 @@ { | ||
| }, | ||
| "version": "0.4.10", | ||
| "version": "0.4.11", | ||
| "engines": { | ||
| "node": ">=16.0.0" | ||
| "node": ">=16", | ||
| "bun": ">=1", | ||
| "deno": ">=2" | ||
| }, | ||
@@ -37,19 +39,15 @@ "keywords": [ | ||
| "types": "./dist/index.d.ts", | ||
| "require": "./dist/index.js", | ||
| "import": "./dist/index.js" | ||
| "default": "./dist/index.js" | ||
| }, | ||
| "./config": { | ||
| "types": "./dist/config.d.ts", | ||
| "import": "./dist/config.js", | ||
| "require": "./dist/config.js" | ||
| "default": "./dist/config.js" | ||
| }, | ||
| "./consts": { | ||
| "types": "./dist/consts.d.ts", | ||
| "import": "./dist/consts.js", | ||
| "require": "./dist/consts.js" | ||
| "default": "./dist/consts.js" | ||
| }, | ||
| "./utils": { | ||
| "types": "./dist/utils/index.d.ts", | ||
| "import": "./dist/utils/index.js", | ||
| "require": "./dist/utils/index.js" | ||
| "default": "./dist/utils/index.js" | ||
| } | ||
@@ -59,6 +57,7 @@ }, | ||
| "build": "npx tsc", | ||
| "test": "vitest" | ||
| "test": "vitest", | ||
| "test:browser": "node ./scripts/gen-browser-tests.mjs && cd tests-browser && pnpm test" | ||
| }, | ||
| "dependencies": { | ||
| "@ecies/ciphers": "^0.2.0", | ||
| "@ecies/ciphers": "^0.2.1", | ||
| "@noble/ciphers": "^1.0.0", | ||
@@ -69,9 +68,9 @@ "@noble/curves": "^1.6.0", | ||
| "devDependencies": { | ||
| "@types/node": "^22.7.9", | ||
| "@vitest/coverage-v8": "^2.1.3", | ||
| "@types/node": "^22.9.0", | ||
| "@vitest/coverage-v8": "^2.1.4", | ||
| "typescript": "^5.6.3", | ||
| "undici": "^6.20.1", | ||
| "vitest": "^2.1.3" | ||
| "vitest": "^2.1.4" | ||
| }, | ||
| "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" | ||
| "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee" | ||
| } |
+25
-2
@@ -41,8 +41,21 @@ # eciesjs | ||
| ## Browser Support | ||
| ## Multi-platform Support | ||
| ### Browser | ||
| This library is browser-friendly, check the [`example/browser`](./example/browser) directory for details. Currently it's necessary to polyfill `Buffer` for backward compatibility. From v0.5.0, it can run in browsers as is. | ||
| If you want a WASM version to run directly in modern browsers or on some blockchains, check [`ecies-wasm`](https://github.com/ecies/rs-wasm). | ||
| If you want a WASM version to run directly in modern browsers or on some blockchains, you can also try [`ecies-wasm`](https://github.com/ecies/rs-wasm). | ||
| ### Bun/Deno | ||
| For bun/deno, see [`example/runtime`](./example/runtime). There are some limitations currently: | ||
| - `xchacha20` does not work on bun | ||
| - Only `aes-256-gcm` with 12 bytes nonce works on deno | ||
| ### React Native | ||
| See the [React Native demo](https://github.com/ecies/js-rn-demo). | ||
| ## API | ||
@@ -144,2 +157,4 @@ | ||
| > If you don't know how to choose between x25519 and ed25519, just use the dedicated key exchange function x25519 for efficiency. | ||
| > | ||
| > Because any 32-byte data is a valid curve25519 public key, the payload would seem random. This property is excellent for circumventing censorship by adversaries. | ||
@@ -158,2 +173,10 @@ ### Secp256k1-specific configuration | ||
| ### Which configuration should I choose? | ||
| For compatibility with other [ecies libraries](https://github.com/orgs/ecies/repositories), start with the default (secp256k1 with AES-256-GCM). | ||
| For speed and security, pick x25519 with XChaCha20-Poly1305. | ||
| If you know exactly what you are doing, configure as you wish or build your own ecies logic with this library. | ||
| ## Security Audit | ||
@@ -160,0 +183,0 @@ |
35191
19.16%555
16.6%189
13.86%Updated