@stacks/encryption
Advanced tools
Comparing version 3.5.1-beta.0 to 3.5.1-beta.1
@@ -76,3 +76,3 @@ "use strict"; | ||
async function createCipher() { | ||
const cryptoLib = await cryptoUtils_1.getCryptoLib(); | ||
const cryptoLib = await (0, cryptoUtils_1.getCryptoLib)(); | ||
if (cryptoLib.name === 'subtleCrypto') { | ||
@@ -79,0 +79,0 @@ return new WebCryptoAesCipher(cryptoLib.lib); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verifyECDSA = exports.signECDSA = exports.decryptECIES = exports.encryptECIES = exports.eciesGetJsonStringLength = exports.getSignedCipherObjectWrapper = exports.getCipherObjectWrapper = exports.getBufferFromBN = exports.getHexFromBN = exports.aes256CbcEncrypt = exports.InvalidPublicKeyReason = void 0; | ||
const hmac_1 = require("@noble/hashes/hmac"); | ||
const sha256_1 = require("@noble/hashes/sha256"); | ||
const utils_1 = require("@noble/hashes/utils"); | ||
const secp256k1_1 = require("@noble/secp256k1"); | ||
const common_1 = require("@stacks/common"); | ||
const secp256k1_1 = require("@noble/secp256k1"); | ||
const common_2 = require("@stacks/common"); | ||
const aesCipher_1 = require("./aesCipher"); | ||
const hmacSha256_1 = require("./hmacSha256"); | ||
const keys_1 = require("./keys"); | ||
const sha2Hash_1 = require("./sha2Hash"); | ||
const hmacSha256_1 = require("./hmacSha256"); | ||
const aesCipher_1 = require("./aesCipher"); | ||
const utils_1 = require("./utils"); | ||
const hmac_1 = require("@noble/hashes/hmac"); | ||
const sha256_1 = require("@noble/hashes/sha256"); | ||
const utils_2 = require("@noble/hashes/utils"); | ||
const utils_2 = require("./utils"); | ||
secp256k1_1.utils.hmacSha256Sync = (key, ...msgs) => { | ||
@@ -26,3 +25,3 @@ const h = hmac_1.hmac.create(sha256_1.sha256, key); | ||
async function aes256CbcEncrypt(iv, key, plaintext) { | ||
const cipher = await aesCipher_1.createCipher(); | ||
const cipher = await (0, aesCipher_1.createCipher)(); | ||
const result = await cipher.encrypt('aes-256-cbc', key, iv, plaintext); | ||
@@ -33,3 +32,3 @@ return result; | ||
async function aes256CbcDecrypt(iv, key, ciphertext) { | ||
const cipher = await aesCipher_1.createCipher(); | ||
const cipher = await (0, aesCipher_1.createCipher)(); | ||
const result = await cipher.decrypt('aes-256-cbc', key, iv, ciphertext); | ||
@@ -39,3 +38,3 @@ return result; | ||
async function hmacSha256(key, content) { | ||
const hmacSha256 = await hmacSha256_1.createHmacSha256(); | ||
const hmacSha256 = await (0, hmacSha256_1.createHmacSha256)(); | ||
return hmacSha256.digest(key, content); | ||
@@ -54,3 +53,3 @@ } | ||
function sharedSecretToKeys(sharedSecret) { | ||
const hashedSecret = sha2Hash_1.hashSha512Sync(sharedSecret); | ||
const hashedSecret = (0, sha2Hash_1.hashSha512Sync)(sharedSecret); | ||
return { | ||
@@ -155,3 +154,3 @@ encryptionKey: hashedSecret.slice(0, 32), | ||
const { payloadShell, payloadValuesLength } = getCipherObjectWrapper(opts); | ||
const cipherTextLength = utils_1.getAesCbcOutputLength(opts.contentLength); | ||
const cipherTextLength = (0, utils_2.getAesCbcOutputLength)(opts.contentLength); | ||
let encodedCipherTextLength; | ||
@@ -162,3 +161,3 @@ if (!opts.cipherTextEncoding || opts.cipherTextEncoding === 'hex') { | ||
else if (opts.cipherTextEncoding === 'base64') { | ||
encodedCipherTextLength = utils_1.getBase64OutputLength(cipherTextLength); | ||
encodedCipherTextLength = (0, utils_2.getBase64OutputLength)(cipherTextLength); | ||
} | ||
@@ -186,4 +185,4 @@ else { | ||
const ephemeralPrivateKey = secp256k1_1.utils.randomPrivateKey(); | ||
const ephemeralPublicKey = secp256k1_1.getPublicKey(ephemeralPrivateKey, true); | ||
let sharedSecret = secp256k1_1.getSharedSecret(ephemeralPrivateKey, publicKey, true); | ||
const ephemeralPublicKey = (0, secp256k1_1.getPublicKey)(ephemeralPrivateKey, true); | ||
let sharedSecret = (0, secp256k1_1.getSharedSecret)(ephemeralPrivateKey, publicKey, true); | ||
sharedSecret = sharedSecret.slice(1); | ||
@@ -193,3 +192,3 @@ const sharedKeys = sharedSecretToKeys(common_1.Buffer.from(sharedSecret)); | ||
const cipherText = await aes256CbcEncrypt(common_1.Buffer.from(initializationVector), sharedKeys.encryptionKey, content); | ||
const macData = utils_2.concatBytes(initializationVector, ephemeralPublicKey, cipherText); | ||
const macData = (0, utils_1.concatBytes)(initializationVector, ephemeralPublicKey, cipherText); | ||
const mac = await hmacSha256(sharedKeys.hmacKey, common_1.Buffer.from(macData)); | ||
@@ -221,10 +220,10 @@ let cipherTextString; | ||
if (!cipherObject.ephemeralPK) { | ||
throw new common_2.FailedDecryptionError('Unable to get public key from cipher object. ' + | ||
throw new common_1.FailedDecryptionError('Unable to get public key from cipher object. ' + | ||
'You might be trying to decrypt an unencrypted object.'); | ||
} | ||
const ephemeralPK = cipherObject.ephemeralPK; | ||
let sharedSecret = secp256k1_1.getSharedSecret(privateKey, ephemeralPK, true); | ||
let sharedSecret = (0, secp256k1_1.getSharedSecret)(privateKey, ephemeralPK, true); | ||
sharedSecret = sharedSecret.slice(1); | ||
const sharedKeys = sharedSecretToKeys(common_1.Buffer.from(sharedSecret)); | ||
const ivBuffer = utils_2.hexToBytes(cipherObject.iv); | ||
const ivBuffer = (0, utils_1.hexToBytes)(cipherObject.iv); | ||
let cipherTextBuffer; | ||
@@ -240,7 +239,7 @@ if (!cipherObject.cipherTextEncoding || cipherObject.cipherTextEncoding === 'hex') { | ||
} | ||
const macData = utils_2.concatBytes(ivBuffer, utils_2.hexToBytes(ephemeralPK), cipherTextBuffer); | ||
const macData = (0, utils_1.concatBytes)(ivBuffer, (0, utils_1.hexToBytes)(ephemeralPK), cipherTextBuffer); | ||
const actualMac = await hmacSha256(sharedKeys.hmacKey, common_1.Buffer.from(macData)); | ||
const expectedMac = utils_2.hexToBytes(cipherObject.mac); | ||
const expectedMac = (0, utils_1.hexToBytes)(cipherObject.mac); | ||
if (!equalConstTime(common_1.Buffer.from(expectedMac), actualMac)) { | ||
throw new common_2.FailedDecryptionError('Decryption failed: failure in MAC check'); | ||
throw new common_1.FailedDecryptionError('Decryption failed: failure in MAC check'); | ||
} | ||
@@ -258,5 +257,5 @@ const plainText = await aes256CbcDecrypt(common_1.Buffer.from(ivBuffer), sharedKeys.encryptionKey, cipherTextBuffer); | ||
const contentBuffer = content instanceof common_1.Buffer ? content : common_1.Buffer.from(content); | ||
const publicKey = keys_1.getPublicKeyFromPrivate(privateKey); | ||
const contentHash = sha2Hash_1.hashSha256Sync(contentBuffer); | ||
const signature = secp256k1_1.signSync(contentHash, privateKey); | ||
const publicKey = (0, keys_1.getPublicKeyFromPrivate)(privateKey); | ||
const contentHash = (0, sha2Hash_1.hashSha256Sync)(contentBuffer); | ||
const signature = (0, secp256k1_1.signSync)(contentHash, privateKey); | ||
return { | ||
@@ -278,6 +277,6 @@ signature: secp256k1_1.utils.bytesToHex(signature), | ||
const contentBuffer = getBuffer(content); | ||
const contentHash = sha2Hash_1.hashSha256Sync(contentBuffer); | ||
return secp256k1_1.verify(signature, contentHash, publicKey); | ||
const contentHash = (0, sha2Hash_1.hashSha256Sync)(contentBuffer); | ||
return (0, secp256k1_1.verify)(signature, contentHash, publicKey); | ||
} | ||
exports.verifyECDSA = verifyECDSA; | ||
//# sourceMappingURL=ec.js.map |
@@ -14,3 +14,3 @@ "use strict"; | ||
} | ||
opts.publicKey = keys_1.getPublicKeyFromPrivate(opts.privateKey); | ||
opts.publicKey = (0, keys_1.getPublicKeyFromPrivate)(opts.privateKey); | ||
} | ||
@@ -25,3 +25,3 @@ let wasString; | ||
const contentBuffer = typeof content === 'string' ? common_1.Buffer.from(content) : content; | ||
const cipherObject = await ec_1.encryptECIES(opts.publicKey, contentBuffer, wasString, opts.cipherTextEncoding); | ||
const cipherObject = await (0, ec_1.encryptECIES)(opts.publicKey, contentBuffer, wasString, opts.cipherTextEncoding); | ||
let cipherPayload = JSON.stringify(cipherObject); | ||
@@ -35,3 +35,3 @@ if (opts.sign) { | ||
} | ||
const signatureObject = ec_1.signECDSA(privateKey, cipherPayload); | ||
const signatureObject = (0, ec_1.signECDSA)(privateKey, cipherPayload); | ||
const signedCipherObject = { | ||
@@ -54,3 +54,3 @@ signature: signatureObject.signature, | ||
const cipherObject = JSON.parse(content); | ||
return ec_1.decryptECIES(opts.privateKey, cipherObject); | ||
return (0, ec_1.decryptECIES)(opts.privateKey, cipherObject); | ||
} | ||
@@ -57,0 +57,0 @@ catch (err) { |
@@ -1,12 +0,11 @@ | ||
import { Buffer } from '@stacks/common'; | ||
import { getPublicKey, getSharedSecret, utils, signSync, verify, Point } from '@noble/secp256k1'; | ||
import { FailedDecryptionError } from '@stacks/common'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { concatBytes, hexToBytes } from '@noble/hashes/utils'; | ||
import { getPublicKey, getSharedSecret, Point, signSync, utils, verify } from '@noble/secp256k1'; | ||
import { Buffer, FailedDecryptionError } from '@stacks/common'; | ||
import { createCipher } from './aesCipher'; | ||
import { createHmacSha256 } from './hmacSha256'; | ||
import { getPublicKeyFromPrivate } from './keys'; | ||
import { hashSha256Sync, hashSha512Sync } from './sha2Hash'; | ||
import { createHmacSha256 } from './hmacSha256'; | ||
import { createCipher } from './aesCipher'; | ||
import { getAesCbcOutputLength, getBase64OutputLength } from './utils'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { hexToBytes, concatBytes } from '@noble/hashes/utils'; | ||
utils.hmacSha256Sync = (key, ...msgs) => { | ||
@@ -13,0 +12,0 @@ const h = hmac.create(sha256, key); |
import { Buffer } from '@stacks/common'; | ||
import { encryptECIES, decryptECIES, signECDSA, } from './ec'; | ||
import { decryptECIES, encryptECIES, signECDSA, } from './ec'; | ||
import { getPublicKeyFromPrivate } from './keys'; | ||
@@ -4,0 +4,0 @@ export async function encryptContent(content, options) { |
/// <reference types="node" /> | ||
import { ECPair, Network } from 'bitcoinjs-lib'; | ||
export declare function getEntropy(arg: number): Buffer; | ||
export declare function makeECPrivateKey(): string; | ||
export declare function base58Encode(hash: Buffer): string; | ||
export declare function hashToBase58Check(hash: Buffer): string; | ||
export declare function publicKeyToAddress(publicKey: string | Buffer): string; | ||
export declare function getPublicKeyFromPrivate(privateKey: string | Buffer): string; | ||
export declare function hexStringToECPair(skHex: string, network?: Network): ECPair.ECPairInterface; | ||
export declare function ecPairToHexString(secretKey: ECPair.ECPairInterface): string; | ||
export declare function ecPairToAddress(keyPair: ECPair.ECPairInterface): string; | ||
export declare function ecSign(messageHash: Buffer, hexPrivateKey: string | Buffer): Buffer; | ||
export declare function ecPrivateKeyToHexString(privateKey: Buffer): string; | ||
export declare function isValidPrivateKey(privateKey: string | Buffer): boolean; | ||
export declare function compressPrivateKey(privateKey: string | Buffer): Buffer; |
@@ -1,63 +0,50 @@ | ||
import { Buffer } from '@stacks/common'; | ||
import { ECPair, address, networks } from 'bitcoinjs-lib'; | ||
import { randomBytes } from './cryptoRandom'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { getPublicKey as nobleGetPublicKey, signSync, utils } from '@noble/secp256k1'; | ||
import { Buffer, privateKeyToBuffer, PRIVATE_KEY_COMPRESSED_LENGTH } from '@stacks/common'; | ||
import base58 from 'bs58'; | ||
import { hashRipemd160 } from './hashRipemd160'; | ||
import { hashSha256Sync } from './sha2Hash'; | ||
import { hashRipemd160 } from './hashRipemd160'; | ||
export function getEntropy(arg) { | ||
if (!arg) { | ||
arg = 32; | ||
} | ||
return randomBytes(arg); | ||
} | ||
const BITCOIN_PUBKEYHASH = 0x00; | ||
utils.hmacSha256Sync = (key, ...msgs) => { | ||
const h = hmac.create(sha256, key); | ||
msgs.forEach(msg => h.update(msg)); | ||
return h.digest(); | ||
}; | ||
export function makeECPrivateKey() { | ||
const keyPair = ECPair.makeRandom({ rng: getEntropy }); | ||
return keyPair.privateKey.toString('hex'); | ||
return Buffer.from(utils.randomPrivateKey()).toString('hex'); | ||
} | ||
export function base58Encode(hash) { | ||
const checksum = sha256(sha256(hash)); | ||
return base58.encode(Buffer.concat([hash, checksum], hash.length + 4)); | ||
} | ||
export function hashToBase58Check(hash) { | ||
return base58Encode(Buffer.from([BITCOIN_PUBKEYHASH, ...hash].slice(0, 21))); | ||
} | ||
export function publicKeyToAddress(publicKey) { | ||
const publicKeyBuffer = Buffer.isBuffer(publicKey) ? publicKey : Buffer.from(publicKey, 'hex'); | ||
const publicKeyHash160 = hashRipemd160(hashSha256Sync(publicKeyBuffer)); | ||
const result = address.toBase58Check(publicKeyHash160, networks.bitcoin.pubKeyHash); | ||
return result; | ||
return hashToBase58Check(publicKeyHash160); | ||
} | ||
export function getPublicKeyFromPrivate(privateKey) { | ||
const privateKeyBuffer = Buffer.isBuffer(privateKey) | ||
? privateKey | ||
: Buffer.from(privateKey, 'hex'); | ||
const keyPair = ECPair.fromPrivateKey(privateKeyBuffer); | ||
return keyPair.publicKey.toString('hex'); | ||
const privateKeyBuffer = privateKeyToBuffer(privateKey); | ||
return Buffer.from(nobleGetPublicKey(privateKeyBuffer.slice(0, 32), true)).toString('hex'); | ||
} | ||
export function hexStringToECPair(skHex, network) { | ||
const ecPairOptions = { | ||
network: network || networks.bitcoin, | ||
compressed: true, | ||
}; | ||
if (skHex.length === 66) { | ||
if (skHex.slice(64) !== '01') { | ||
throw new Error('Improperly formatted private-key hex string. 66-length hex usually ' + | ||
'indicates compressed key, but last byte must be == 1'); | ||
} | ||
return ECPair.fromPrivateKey(Buffer.from(skHex.slice(0, 64), 'hex'), ecPairOptions); | ||
} | ||
else if (skHex.length === 64) { | ||
ecPairOptions.compressed = false; | ||
return ECPair.fromPrivateKey(Buffer.from(skHex, 'hex'), ecPairOptions); | ||
} | ||
else { | ||
throw new Error('Improperly formatted private-key hex string: length should be 64 or 66.'); | ||
} | ||
export function ecSign(messageHash, hexPrivateKey) { | ||
return Buffer.from(signSync(messageHash, privateKeyToBuffer(hexPrivateKey).slice(0, 32), { | ||
der: false, | ||
})); | ||
} | ||
export function ecPairToHexString(secretKey) { | ||
const ecPointHex = secretKey.privateKey.toString('hex'); | ||
if (secretKey.compressed) { | ||
return `${ecPointHex}01`; | ||
} | ||
else { | ||
return ecPointHex; | ||
} | ||
export function ecPrivateKeyToHexString(privateKey) { | ||
return privateKey.toString('hex'); | ||
} | ||
export function ecPairToAddress(keyPair) { | ||
const sha256 = hashSha256Sync(keyPair.publicKey); | ||
const hash160 = hashRipemd160(sha256); | ||
return address.toBase58Check(hash160, keyPair.network.pubKeyHash); | ||
export function isValidPrivateKey(privateKey) { | ||
return utils.isValidPrivateKey(privateKeyToBuffer(privateKey)); | ||
} | ||
export function compressPrivateKey(privateKey) { | ||
const privateKeyBuffer = privateKeyToBuffer(privateKey); | ||
return privateKeyBuffer.length == PRIVATE_KEY_COMPRESSED_LENGTH | ||
? privateKeyBuffer | ||
: Buffer.concat([privateKeyBuffer, Buffer.from([1])]); | ||
} | ||
//# sourceMappingURL=keys.js.map |
import { Buffer } from '@stacks/common'; | ||
import { validateMnemonic, mnemonicToEntropy, entropyToMnemonic } from 'bip39'; | ||
import { validateMnemonic, mnemonicToEntropy, entropyToMnemonic } from '@scure/bip39'; | ||
import { wordlist } from '@scure/bip39/wordlists/english'; | ||
import { randomBytes } from './cryptoRandom'; | ||
@@ -11,3 +12,4 @@ import { createSha2Hash } from './sha2Hash'; | ||
try { | ||
mnemonicEntropy = mnemonicToEntropy(phrase); | ||
const entropyBytes = mnemonicToEntropy(phrase, wordlist); | ||
mnemonicEntropy = Buffer.from(entropyBytes).toString('hex'); | ||
} | ||
@@ -64,3 +66,3 @@ catch (error) { | ||
try { | ||
mnemonic = entropyToMnemonic(decryptedResult); | ||
mnemonic = entropyToMnemonic(decryptedResult, wordlist); | ||
} | ||
@@ -72,3 +74,3 @@ catch (error) { | ||
} | ||
if (!validateMnemonic(mnemonic)) { | ||
if (!validateMnemonic(mnemonic, wordlist)) { | ||
throw new PasswordError('Wrong password (invalid plaintext)'); | ||
@@ -75,0 +77,0 @@ } |
@@ -47,3 +47,3 @@ "use strict"; | ||
function createHashRipemd160() { | ||
const nodeCryptoCreateHash = cryptoUtils_1.isNodeCryptoAvailable(nodeCrypto => { | ||
const nodeCryptoCreateHash = (0, cryptoUtils_1.isNodeCryptoAvailable)(nodeCrypto => { | ||
if (typeof nodeCrypto.createHash === 'function') { | ||
@@ -50,0 +50,0 @@ return nodeCrypto.createHash; |
@@ -28,3 +28,3 @@ "use strict"; | ||
async function createHmacSha256() { | ||
const cryptoLib = await cryptoUtils_1.getCryptoLib(); | ||
const cryptoLib = await (0, cryptoUtils_1.getCryptoLib)(); | ||
if (cryptoLib.name === 'subtleCrypto') { | ||
@@ -31,0 +31,0 @@ return new WebCryptoHmacSha256(cryptoLib.lib); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -6,0 +10,0 @@ if (k2 === undefined) k2 = k; |
/// <reference types="node" /> | ||
import { ECPair, Network } from 'bitcoinjs-lib'; | ||
export declare function getEntropy(arg: number): Buffer; | ||
export declare function makeECPrivateKey(): string; | ||
export declare function base58Encode(hash: Buffer): string; | ||
export declare function hashToBase58Check(hash: Buffer): string; | ||
export declare function publicKeyToAddress(publicKey: string | Buffer): string; | ||
export declare function getPublicKeyFromPrivate(privateKey: string | Buffer): string; | ||
export declare function hexStringToECPair(skHex: string, network?: Network): ECPair.ECPairInterface; | ||
export declare function ecPairToHexString(secretKey: ECPair.ECPairInterface): string; | ||
export declare function ecPairToAddress(keyPair: ECPair.ECPairInterface): string; | ||
export declare function ecSign(messageHash: Buffer, hexPrivateKey: string | Buffer): Buffer; | ||
export declare function ecPrivateKeyToHexString(privateKey: Buffer): string; | ||
export declare function isValidPrivateKey(privateKey: string | Buffer): boolean; | ||
export declare function compressPrivateKey(privateKey: string | Buffer): Buffer; |
102
dist/keys.js
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ecPairToAddress = exports.ecPairToHexString = exports.hexStringToECPair = exports.getPublicKeyFromPrivate = exports.publicKeyToAddress = exports.makeECPrivateKey = exports.getEntropy = void 0; | ||
exports.compressPrivateKey = exports.isValidPrivateKey = exports.ecPrivateKeyToHexString = exports.ecSign = exports.getPublicKeyFromPrivate = exports.publicKeyToAddress = exports.hashToBase58Check = exports.base58Encode = exports.makeECPrivateKey = void 0; | ||
const hmac_1 = require("@noble/hashes/hmac"); | ||
const sha256_1 = require("@noble/hashes/sha256"); | ||
const secp256k1_1 = require("@noble/secp256k1"); | ||
const common_1 = require("@stacks/common"); | ||
const bitcoinjs_lib_1 = require("bitcoinjs-lib"); | ||
const cryptoRandom_1 = require("./cryptoRandom"); | ||
const bs58_1 = __importDefault(require("bs58")); | ||
const hashRipemd160_1 = require("./hashRipemd160"); | ||
const sha2Hash_1 = require("./sha2Hash"); | ||
const hashRipemd160_1 = require("./hashRipemd160"); | ||
function getEntropy(arg) { | ||
if (!arg) { | ||
arg = 32; | ||
} | ||
return cryptoRandom_1.randomBytes(arg); | ||
} | ||
exports.getEntropy = getEntropy; | ||
const BITCOIN_PUBKEYHASH = 0x00; | ||
secp256k1_1.utils.hmacSha256Sync = (key, ...msgs) => { | ||
const h = hmac_1.hmac.create(sha256_1.sha256, key); | ||
msgs.forEach(msg => h.update(msg)); | ||
return h.digest(); | ||
}; | ||
function makeECPrivateKey() { | ||
const keyPair = bitcoinjs_lib_1.ECPair.makeRandom({ rng: getEntropy }); | ||
return keyPair.privateKey.toString('hex'); | ||
return common_1.Buffer.from(secp256k1_1.utils.randomPrivateKey()).toString('hex'); | ||
} | ||
exports.makeECPrivateKey = makeECPrivateKey; | ||
function base58Encode(hash) { | ||
const checksum = (0, sha256_1.sha256)((0, sha256_1.sha256)(hash)); | ||
return bs58_1.default.encode(common_1.Buffer.concat([hash, checksum], hash.length + 4)); | ||
} | ||
exports.base58Encode = base58Encode; | ||
function hashToBase58Check(hash) { | ||
return base58Encode(common_1.Buffer.from([BITCOIN_PUBKEYHASH, ...hash].slice(0, 21))); | ||
} | ||
exports.hashToBase58Check = hashToBase58Check; | ||
function publicKeyToAddress(publicKey) { | ||
const publicKeyBuffer = common_1.Buffer.isBuffer(publicKey) ? publicKey : common_1.Buffer.from(publicKey, 'hex'); | ||
const publicKeyHash160 = hashRipemd160_1.hashRipemd160(sha2Hash_1.hashSha256Sync(publicKeyBuffer)); | ||
const result = bitcoinjs_lib_1.address.toBase58Check(publicKeyHash160, bitcoinjs_lib_1.networks.bitcoin.pubKeyHash); | ||
return result; | ||
const publicKeyHash160 = (0, hashRipemd160_1.hashRipemd160)((0, sha2Hash_1.hashSha256Sync)(publicKeyBuffer)); | ||
return hashToBase58Check(publicKeyHash160); | ||
} | ||
exports.publicKeyToAddress = publicKeyToAddress; | ||
function getPublicKeyFromPrivate(privateKey) { | ||
const privateKeyBuffer = common_1.Buffer.isBuffer(privateKey) | ||
? privateKey | ||
: common_1.Buffer.from(privateKey, 'hex'); | ||
const keyPair = bitcoinjs_lib_1.ECPair.fromPrivateKey(privateKeyBuffer); | ||
return keyPair.publicKey.toString('hex'); | ||
const privateKeyBuffer = (0, common_1.privateKeyToBuffer)(privateKey); | ||
return common_1.Buffer.from((0, secp256k1_1.getPublicKey)(privateKeyBuffer.slice(0, 32), true)).toString('hex'); | ||
} | ||
exports.getPublicKeyFromPrivate = getPublicKeyFromPrivate; | ||
function hexStringToECPair(skHex, network) { | ||
const ecPairOptions = { | ||
network: network || bitcoinjs_lib_1.networks.bitcoin, | ||
compressed: true, | ||
}; | ||
if (skHex.length === 66) { | ||
if (skHex.slice(64) !== '01') { | ||
throw new Error('Improperly formatted private-key hex string. 66-length hex usually ' + | ||
'indicates compressed key, but last byte must be == 1'); | ||
} | ||
return bitcoinjs_lib_1.ECPair.fromPrivateKey(common_1.Buffer.from(skHex.slice(0, 64), 'hex'), ecPairOptions); | ||
} | ||
else if (skHex.length === 64) { | ||
ecPairOptions.compressed = false; | ||
return bitcoinjs_lib_1.ECPair.fromPrivateKey(common_1.Buffer.from(skHex, 'hex'), ecPairOptions); | ||
} | ||
else { | ||
throw new Error('Improperly formatted private-key hex string: length should be 64 or 66.'); | ||
} | ||
function ecSign(messageHash, hexPrivateKey) { | ||
return common_1.Buffer.from((0, secp256k1_1.signSync)(messageHash, (0, common_1.privateKeyToBuffer)(hexPrivateKey).slice(0, 32), { | ||
der: false, | ||
})); | ||
} | ||
exports.hexStringToECPair = hexStringToECPair; | ||
function ecPairToHexString(secretKey) { | ||
const ecPointHex = secretKey.privateKey.toString('hex'); | ||
if (secretKey.compressed) { | ||
return `${ecPointHex}01`; | ||
} | ||
else { | ||
return ecPointHex; | ||
} | ||
exports.ecSign = ecSign; | ||
function ecPrivateKeyToHexString(privateKey) { | ||
return privateKey.toString('hex'); | ||
} | ||
exports.ecPairToHexString = ecPairToHexString; | ||
function ecPairToAddress(keyPair) { | ||
const sha256 = sha2Hash_1.hashSha256Sync(keyPair.publicKey); | ||
const hash160 = hashRipemd160_1.hashRipemd160(sha256); | ||
return bitcoinjs_lib_1.address.toBase58Check(hash160, keyPair.network.pubKeyHash); | ||
exports.ecPrivateKeyToHexString = ecPrivateKeyToHexString; | ||
function isValidPrivateKey(privateKey) { | ||
return secp256k1_1.utils.isValidPrivateKey((0, common_1.privateKeyToBuffer)(privateKey)); | ||
} | ||
exports.ecPairToAddress = ecPairToAddress; | ||
exports.isValidPrivateKey = isValidPrivateKey; | ||
function compressPrivateKey(privateKey) { | ||
const privateKeyBuffer = (0, common_1.privateKeyToBuffer)(privateKey); | ||
return privateKeyBuffer.length == common_1.PRIVATE_KEY_COMPRESSED_LENGTH | ||
? privateKeyBuffer | ||
: common_1.Buffer.concat([privateKeyBuffer, common_1.Buffer.from([1])]); | ||
} | ||
exports.compressPrivateKey = compressPrivateKey; | ||
//# sourceMappingURL=keys.js.map |
@@ -110,3 +110,3 @@ "use strict"; | ||
async function createPbkdf2() { | ||
const cryptoLib = await cryptoUtils_1.getCryptoLib(); | ||
const cryptoLib = await (0, cryptoUtils_1.getCryptoLib)(); | ||
if (cryptoLib.name === 'subtleCrypto') { | ||
@@ -113,0 +113,0 @@ return new WebCryptoPbkdf2(cryptoLib.lib); |
@@ -52,3 +52,3 @@ "use strict"; | ||
async function createSha2Hash() { | ||
const cryptoLib = await cryptoUtils_1.getCryptoLib(); | ||
const cryptoLib = await (0, cryptoUtils_1.getCryptoLib)(); | ||
if (cryptoLib.name === 'subtleCrypto') { | ||
@@ -55,0 +55,0 @@ return new WebCryptoSha2Hash(cryptoLib.lib); |
@@ -8,8 +8,12 @@ /*! | ||
/*! For license information please see index.js.LICENSE.txt */ | ||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */ | ||
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */ | ||
/*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ | ||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */ | ||
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */ | ||
/*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */ |
@@ -5,3 +5,4 @@ "use strict"; | ||
const common_1 = require("@stacks/common"); | ||
const bip39_1 = require("bip39"); | ||
const bip39_1 = require("@scure/bip39"); | ||
const english_1 = require("@scure/bip39/wordlists/english"); | ||
const cryptoRandom_1 = require("./cryptoRandom"); | ||
@@ -15,3 +16,4 @@ const sha2Hash_1 = require("./sha2Hash"); | ||
try { | ||
mnemonicEntropy = bip39_1.mnemonicToEntropy(phrase); | ||
const entropyBytes = (0, bip39_1.mnemonicToEntropy)(phrase, english_1.wordlist); | ||
mnemonicEntropy = common_1.Buffer.from(entropyBytes).toString('hex'); | ||
} | ||
@@ -24,3 +26,3 @@ catch (error) { | ||
const plaintextNormalized = common_1.Buffer.from(mnemonicEntropy, 'hex'); | ||
const pbkdf2 = await pbkdf2_1.createPbkdf2(); | ||
const pbkdf2 = await (0, pbkdf2_1.createPbkdf2)(); | ||
let salt; | ||
@@ -31,3 +33,3 @@ if (opts && opts.getRandomBytes) { | ||
else { | ||
salt = cryptoRandom_1.randomBytes(16); | ||
salt = (0, cryptoRandom_1.randomBytes)(16); | ||
} | ||
@@ -38,6 +40,6 @@ const keysAndIV = await pbkdf2.derive(password, salt, 100000, 48, 'sha512'); | ||
const iv = keysAndIV.slice(32, 48); | ||
const cipher = await aesCipher_1.createCipher(); | ||
const cipher = await (0, aesCipher_1.createCipher)(); | ||
const cipherText = await cipher.encrypt('aes-128-cbc', encKey, iv, plaintextNormalized); | ||
const hmacPayload = common_1.Buffer.concat([salt, cipherText]); | ||
const hmacSha256 = await hmacSha256_1.createHmacSha256(); | ||
const hmacSha256 = await (0, hmacSha256_1.createHmacSha256)(); | ||
const hmacDigest = await hmacSha256.digest(macKey, hmacPayload); | ||
@@ -55,3 +57,3 @@ const payload = common_1.Buffer.concat([salt, hmacDigest, cipherText]); | ||
const hmacPayload = common_1.Buffer.concat([salt, cipherText]); | ||
const pbkdf2 = await pbkdf2_1.createPbkdf2(); | ||
const pbkdf2 = await (0, pbkdf2_1.createPbkdf2)(); | ||
const keysAndIV = await pbkdf2.derive(password, salt, 100000, 48, 'sha512'); | ||
@@ -61,7 +63,7 @@ const encKey = keysAndIV.slice(0, 16); | ||
const iv = keysAndIV.slice(32, 48); | ||
const decipher = await aesCipher_1.createCipher(); | ||
const decipher = await (0, aesCipher_1.createCipher)(); | ||
const decryptedResult = await decipher.decrypt('aes-128-cbc', encKey, iv, cipherText); | ||
const hmacSha256 = await hmacSha256_1.createHmacSha256(); | ||
const hmacSha256 = await (0, hmacSha256_1.createHmacSha256)(); | ||
const hmacDigest = await hmacSha256.digest(macKey, hmacPayload); | ||
const sha2Hash = await sha2Hash_1.createSha2Hash(); | ||
const sha2Hash = await (0, sha2Hash_1.createSha2Hash)(); | ||
const hmacSigHash = await sha2Hash.digest(hmacSig); | ||
@@ -74,3 +76,3 @@ const hmacDigestHash = await sha2Hash.digest(hmacDigest); | ||
try { | ||
mnemonic = bip39_1.entropyToMnemonic(decryptedResult); | ||
mnemonic = (0, bip39_1.entropyToMnemonic)(decryptedResult, english_1.wordlist); | ||
} | ||
@@ -82,3 +84,3 @@ catch (error) { | ||
} | ||
if (!bip39_1.validateMnemonic(mnemonic)) { | ||
if (!(0, bip39_1.validateMnemonic)(mnemonic, english_1.wordlist)) { | ||
throw new PasswordError('Wrong password (invalid plaintext)'); | ||
@@ -85,0 +87,0 @@ } |
{ | ||
"name": "@stacks/encryption", | ||
"version": "3.5.1-beta.0", | ||
"version": "3.5.1-beta.1", | ||
"description": "Encryption utilities for Stacks", | ||
@@ -37,8 +37,8 @@ "author": "yknl <yukanliao@gmail.com>", | ||
"@noble/secp256k1": "^1.5.5", | ||
"@stacks/common": "^3.5.1-beta.0", | ||
"@scure/bip39": "^1.0.0", | ||
"@stacks/common": "^3.3.0", | ||
"@types/bn.js": "^4.11.6", | ||
"@types/node": "^14.14.43", | ||
"bip39": "^3.0.2", | ||
"bitcoinjs-lib": "^5.2.0", | ||
"bn.js": "^5.2.0", | ||
"bs58": "^5.0.0", | ||
"ripemd160-min": "^0.0.6", | ||
@@ -49,2 +49,3 @@ "sha.js": "^2.4.11" | ||
"@peculiar/webcrypto": "^1.1.6", | ||
"@types/bs58check": "^2.1.0", | ||
"@types/elliptic": "^6.4.12", | ||
@@ -54,2 +55,4 @@ "@types/jest": "^26.0.22", | ||
"@types/triplesec": "^3.0.0", | ||
"bitcoinjs-lib": "^5.2.0", | ||
"bs58check": "^2.1.2", | ||
"crypto-browserify": "^3.12.0", | ||
@@ -79,3 +82,3 @@ "elliptic": "^6.5.4", | ||
"unpkg": "dist/umd/index.js", | ||
"gitHead": "1b5f2acfcb51c551b8f21de5356e96c50c163b0f" | ||
"gitHead": "191f4a492cbf6d3b20462dc9d935155c2bed330a" | ||
} |
@@ -12,2 +12,3 @@ # @stacks/encryption | ||
### Encrypt and decrypt string | ||
```typescript | ||
@@ -22,7 +23,7 @@ import { encryptECIES, decryptECIES } from '@stacks/encryption'; | ||
// Encrypt string with public key | ||
// Encrypt string with public key | ||
const cipherObj = await encryptECIES(publicKey, Buffer.from(testString), true); | ||
// Decrypt the cipher with private key to get the message | ||
const deciphered = await decryptECIES(privateKey, cipherObj) | ||
const deciphered = await decryptECIES(privateKey, cipherObj); | ||
console.log(deciphered); | ||
@@ -37,24 +38,24 @@ ``` | ||
const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229'; | ||
const testString = 'all work and no play makes jack a dull boy' | ||
const testString = 'all work and no play makes jack a dull boy'; | ||
const sigObj = await signECDSA(privateKey, testString) | ||
const sigObj = signECDSA(privateKey, testString); | ||
// Verify content using ECDSA | ||
const result = await verifyECDSA(testString, sigObj.publicKey, sigObj.signature); | ||
const result = verifyECDSA(testString, sigObj.publicKey, sigObj.signature); | ||
console.log(result); // true | ||
``` | ||
### EncryptMnemonic and decryptMnemonic | ||
### `encryptMnemonic` and `decryptMnemonic` | ||
```typescript | ||
import { Buffer } from '@stacks/common'; | ||
import { encryptMnemonic, decryptMnemonic } from '@stacks/encryption'; | ||
import { Buffer } from '@stacks/common'; | ||
const rawPhrase = 'march eager husband pilot waste rely exclude taste ' | ||
+ 'twist donkey actress scene'; | ||
const rawPhrase = 'march eager husband pilot waste rely exclude taste twist donkey actress scene'; | ||
const rawPassword = 'rawPassword'; | ||
const mockSalt = Buffer.from('ff'.repeat(16), 'hex') | ||
const mockSalt = Buffer.from('ff'.repeat(16), 'hex'); | ||
//Encrypt a raw mnemonic phrase to be password protected | ||
// Encrypt a raw mnemonic phrase to be password protected | ||
const encoded = await encryptMnemonic(rawPhrase, rawPassword, { getRandomBytes: () => mockSalt }); | ||
//Decrypt an encrypted mnemonic phrase with a password | ||
// Decrypt an encrypted mnemonic phrase with a password | ||
const decoded = await decryptMnemonic(encoded.toString('hex'), rawPassword); | ||
@@ -65,10 +66,23 @@ | ||
### Make EC PrivateKey | ||
### Private key to address | ||
```typescript | ||
import { getPublicKeyFromPrivate, publicKeyToAddress } from '@stacks/encryption'; | ||
const privateKey = '00cdce6b5f87d38f2a830cae0da82162e1b487f07c5affa8130f01fe1a2a25fb01'; | ||
const expectedAddress = '1WykMawQRnLh7SWmmoRL4qTDNCgAsVRF1'; | ||
const publicKey = getPublicKeyFromPrivate(privateKey); | ||
const address = publicKeyToAddress(publicKey); | ||
console.log(address === expectedAddress); // true | ||
``` | ||
### Make private key | ||
```typescript | ||
import { makeECPrivateKey, publicKeyToAddress } from '@stacks/encryption'; | ||
import { SECP256K1Client } from 'jsontokens'; | ||
// makeECPrivateKey | ||
const privateKey = makeECPrivateKey(); | ||
// Private key is also usable with the jsontokens package | ||
const publicKey = SECP256K1Client.derivePublicKey(privateKey); | ||
@@ -78,21 +92,1 @@ const address = publicKeyToAddress(publicKey); | ||
``` | ||
### EC pair to hex string | ||
```typescript | ||
import { | ||
ecPairToAddress, | ||
ecPairToHexString, | ||
hexStringToECPair, | ||
} from '@stacks/encryption'; | ||
const privateKey = '00cdce6b5f87d38f2a830cae0da82162e1b487f07c5affa8130f01fe1a2a25fb01'; | ||
const expectedAddress = '1WykMawQRnLh7SWmmoRL4qTDNCgAsVRF1'; | ||
const computedECPair = hexStringToECPair(privateKey); | ||
const exToHex = ecPairToHexString(computedECPair); | ||
const address = ecPairToAddress(computedECPair); | ||
console.log(exToHex); | ||
console.log(address === expectedAddress); // true | ||
``` |
@@ -1,13 +0,12 @@ | ||
import { Buffer } from '@stacks/common'; | ||
import { getPublicKey, getSharedSecret, utils, signSync, verify, Point } from '@noble/secp256k1'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { concatBytes, hexToBytes } from '@noble/hashes/utils'; | ||
import { getPublicKey, getSharedSecret, Point, signSync, utils, verify } from '@noble/secp256k1'; | ||
import { Buffer, FailedDecryptionError } from '@stacks/common'; | ||
import * as BN from 'bn.js'; | ||
import { FailedDecryptionError } from '@stacks/common'; | ||
import { createCipher } from './aesCipher'; | ||
import { createHmacSha256 } from './hmacSha256'; | ||
import { getPublicKeyFromPrivate } from './keys'; | ||
import { hashSha256Sync, hashSha512Sync } from './sha2Hash'; | ||
import { createHmacSha256 } from './hmacSha256'; | ||
import { createCipher } from './aesCipher'; | ||
import { getAesCbcOutputLength, getBase64OutputLength } from './utils'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { hexToBytes, concatBytes } from '@noble/hashes/utils'; | ||
@@ -14,0 +13,0 @@ /** |
import { Buffer } from '@stacks/common'; | ||
import { | ||
CipherTextEncoding, | ||
SignedCipherObject, | ||
decryptECIES, | ||
encryptECIES, | ||
decryptECIES, | ||
signECDSA, | ||
SignedCipherObject, | ||
} from './ec'; | ||
import { getPublicKeyFromPrivate } from './keys'; | ||
@@ -11,0 +10,0 @@ |
115
src/keys.ts
@@ -1,18 +0,29 @@ | ||
import { Buffer } from '@stacks/common'; | ||
import { ECPair, address, networks, Network } from 'bitcoinjs-lib'; | ||
import { randomBytes } from './cryptoRandom'; | ||
import { hmac } from '@noble/hashes/hmac'; | ||
import { sha256 } from '@noble/hashes/sha256'; | ||
import { getPublicKey as nobleGetPublicKey, signSync, utils } from '@noble/secp256k1'; | ||
import { Buffer, privateKeyToBuffer, PRIVATE_KEY_COMPRESSED_LENGTH } from '@stacks/common'; | ||
import base58 from 'bs58'; | ||
import { hashRipemd160 } from './hashRipemd160'; | ||
import { hashSha256Sync } from './sha2Hash'; | ||
import { hashRipemd160 } from './hashRipemd160'; | ||
const BITCOIN_PUBKEYHASH = 0x00; | ||
/** | ||
* | ||
* @param numberOfBytes | ||
* | ||
* To use secp256k1.signSync set utils.hmacSha256Sync to a function using noble-hashes | ||
* secp256k1.signSync is the counter part of secp256k1.sign (async version) | ||
* secp256k1.signSync is used within signWithKey in this file | ||
* secp256k1.signSync is used to maintain the semantics of signWithKey while migrating from elliptic lib | ||
* utils.hmacSha256Sync docs: https://github.com/paulmillr/noble-secp256k1 readme file | ||
*/ | ||
utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => { | ||
const h = hmac.create(sha256, key); | ||
msgs.forEach(msg => h.update(msg)); | ||
return h.digest(); | ||
}; | ||
/** | ||
* @ignore | ||
*/ | ||
export function getEntropy(arg: number): Buffer { | ||
if (!arg) { | ||
arg = 32; | ||
} | ||
return randomBytes(arg); | ||
export function makeECPrivateKey() { | ||
return Buffer.from(utils.randomPrivateKey()).toString('hex'); | ||
} | ||
@@ -23,5 +34,5 @@ | ||
*/ | ||
export function makeECPrivateKey() { | ||
const keyPair = ECPair.makeRandom({ rng: getEntropy }); | ||
return keyPair.privateKey!.toString('hex'); | ||
export function base58Encode(hash: Buffer) { | ||
const checksum = sha256(sha256(hash)); | ||
return base58.encode(Buffer.concat([hash, checksum], hash.length + 4)); | ||
} | ||
@@ -32,7 +43,13 @@ | ||
*/ | ||
export function hashToBase58Check(hash: Buffer) { | ||
return base58Encode(Buffer.from([BITCOIN_PUBKEYHASH, ...hash].slice(0, 21))); | ||
} | ||
/** | ||
* @ignore | ||
*/ | ||
export function publicKeyToAddress(publicKey: string | Buffer) { | ||
const publicKeyBuffer = Buffer.isBuffer(publicKey) ? publicKey : Buffer.from(publicKey, 'hex'); | ||
const publicKeyHash160 = hashRipemd160(hashSha256Sync(publicKeyBuffer)); | ||
const result = address.toBase58Check(publicKeyHash160, networks.bitcoin.pubKeyHash); | ||
return result; | ||
return hashToBase58Check(publicKeyHash160); | ||
} | ||
@@ -42,60 +59,44 @@ | ||
* @ignore | ||
* @returns a compressed public key | ||
*/ | ||
export function getPublicKeyFromPrivate(privateKey: string | Buffer) { | ||
const privateKeyBuffer = Buffer.isBuffer(privateKey) | ||
? privateKey | ||
: Buffer.from(privateKey, 'hex'); | ||
const keyPair = ECPair.fromPrivateKey(privateKeyBuffer); | ||
return keyPair.publicKey.toString('hex'); | ||
const privateKeyBuffer = privateKeyToBuffer(privateKey); | ||
// for backwards compatibility we always return a compressed public key, regardless of private key mode | ||
return Buffer.from(nobleGetPublicKey(privateKeyBuffer.slice(0, 32), true)).toString('hex'); | ||
} | ||
/** | ||
* Time | ||
* @private | ||
* @ignore | ||
*/ | ||
export function hexStringToECPair(skHex: string, network?: Network): ECPair.ECPairInterface { | ||
const ecPairOptions = { | ||
network: network || networks.bitcoin, | ||
compressed: true, | ||
}; | ||
export function ecSign(messageHash: Buffer, hexPrivateKey: string | Buffer) { | ||
return Buffer.from( | ||
signSync(messageHash, privateKeyToBuffer(hexPrivateKey).slice(0, 32), { | ||
der: false, | ||
}) | ||
); | ||
} | ||
if (skHex.length === 66) { | ||
if (skHex.slice(64) !== '01') { | ||
throw new Error( | ||
'Improperly formatted private-key hex string. 66-length hex usually ' + | ||
'indicates compressed key, but last byte must be == 1' | ||
); | ||
} | ||
return ECPair.fromPrivateKey(Buffer.from(skHex.slice(0, 64), 'hex'), ecPairOptions); | ||
} else if (skHex.length === 64) { | ||
ecPairOptions.compressed = false; | ||
return ECPair.fromPrivateKey(Buffer.from(skHex, 'hex'), ecPairOptions); | ||
} else { | ||
throw new Error('Improperly formatted private-key hex string: length should be 64 or 66.'); | ||
} | ||
/** | ||
* @ignore | ||
*/ | ||
export function ecPrivateKeyToHexString(privateKey: Buffer): string { | ||
return privateKey.toString('hex'); | ||
} | ||
/** | ||
* | ||
* @ignore | ||
*/ | ||
export function ecPairToHexString(secretKey: ECPair.ECPairInterface) { | ||
const ecPointHex = secretKey.privateKey!.toString('hex'); | ||
if (secretKey.compressed) { | ||
return `${ecPointHex}01`; | ||
} else { | ||
return ecPointHex; | ||
} | ||
export function isValidPrivateKey(privateKey: string | Buffer): boolean { | ||
return utils.isValidPrivateKey(privateKeyToBuffer(privateKey)); | ||
} | ||
/** | ||
* Creates a bitcoin address string from an ECPair | ||
* @private | ||
* @ignore | ||
*/ | ||
export function ecPairToAddress(keyPair: ECPair.ECPairInterface) { | ||
const sha256 = hashSha256Sync(keyPair.publicKey); | ||
const hash160 = hashRipemd160(sha256); | ||
return address.toBase58Check(hash160, keyPair.network.pubKeyHash); | ||
export function compressPrivateKey(privateKey: string | Buffer): Buffer { | ||
const privateKeyBuffer = privateKeyToBuffer(privateKey); | ||
return privateKeyBuffer.length == PRIVATE_KEY_COMPRESSED_LENGTH | ||
? privateKeyBuffer // leave compressed | ||
: Buffer.concat([privateKeyBuffer, Buffer.from([1])]); // compress | ||
} |
import { Buffer } from '@stacks/common'; | ||
import { validateMnemonic, mnemonicToEntropy, entropyToMnemonic } from 'bip39'; | ||
// https://github.com/paulmillr/scure-bip39 | ||
// Secure, audited & minimal implementation of BIP39 mnemonic phrases. | ||
import { validateMnemonic, mnemonicToEntropy, entropyToMnemonic } from '@scure/bip39'; | ||
// Word lists not imported by default as that would increase bundle sizes too much as in case of bitcoinjs/bip39 | ||
// Use default english world list similiar to bitcoinjs/bip39 | ||
// Backward compatible with bitcoinjs/bip39 dependency | ||
// Very small in size as compared to bitcoinjs/bip39 wordlist | ||
// Reference: https://github.com/paulmillr/scure-bip39 | ||
import { wordlist } from '@scure/bip39/wordlists/english'; | ||
import { randomBytes, GetRandomBytes } from './cryptoRandom'; | ||
@@ -29,3 +37,6 @@ import { createSha2Hash } from './sha2Hash'; | ||
// must be bip39 mnemonic | ||
mnemonicEntropy = mnemonicToEntropy(phrase); | ||
// `mnemonicToEntropy` converts mnemonic string to raw entropy in form of byte array | ||
const entropyBytes = mnemonicToEntropy(phrase, wordlist); | ||
// Convert byte array to hex string | ||
mnemonicEntropy = Buffer.from(entropyBytes).toString('hex'); | ||
} catch (error) { | ||
@@ -101,3 +112,4 @@ console.error('Invalid mnemonic phrase provided'); | ||
try { | ||
mnemonic = entropyToMnemonic(decryptedResult); | ||
// Converts raw entropy in form of byte array to mnemonic string | ||
mnemonic = entropyToMnemonic(decryptedResult, wordlist); | ||
} catch (error) { | ||
@@ -108,3 +120,4 @@ console.error('Error thrown by `entropyToMnemonic`'); | ||
} | ||
if (!validateMnemonic(mnemonic)) { | ||
// Validates mnemonic for being 12-24 words contained in `wordlist` | ||
if (!validateMnemonic(mnemonic, wordlist)) { | ||
throw new PasswordError('Wrong password (invalid plaintext)'); | ||
@@ -111,0 +124,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
4216355
24
9196
88
3
1
+ Added@scure/bip39@^1.0.0
+ Addedbs58@^5.0.0
+ Added@scure/base@1.2.4(transitive)
+ Added@scure/bip39@1.5.4(transitive)
+ Addedbase-x@4.0.0(transitive)
+ Addedbs58@5.0.0(transitive)
- Removedbip39@^3.0.2
- Removedbitcoinjs-lib@^5.2.0
- Removed@types/node@10.12.18(transitive)
- Removedbase-x@3.0.10(transitive)
- Removedbech32@1.1.4(transitive)
- Removedbindings@1.5.0(transitive)
- Removedbip174@2.1.1(transitive)
- Removedbip32@2.0.6(transitive)
- Removedbip39@3.1.0(transitive)
- Removedbip66@1.1.5(transitive)
- Removedbitcoin-ops@1.4.1(transitive)
- Removedbitcoinjs-lib@5.2.0(transitive)
- Removedbn.js@4.12.1(transitive)
- Removedbrorand@1.1.0(transitive)
- Removedbs58@4.0.1(transitive)
- Removedbs58check@2.1.2(transitive)
- Removedcipher-base@1.0.6(transitive)
- Removedcreate-hash@1.2.0(transitive)
- Removedcreate-hmac@1.1.7(transitive)
- Removedelliptic@6.6.1(transitive)
- Removedfile-uri-to-path@1.0.0(transitive)
- Removedhash-base@3.1.0(transitive)
- Removedhash.js@1.1.7(transitive)
- Removedhmac-drbg@1.0.1(transitive)
- Removedmd5.js@1.3.5(transitive)
- Removedmerkle-lib@2.0.10(transitive)
- Removedminimalistic-assert@1.0.1(transitive)
- Removedminimalistic-crypto-utils@1.0.1(transitive)
- Removednan@2.22.1(transitive)
- Removedpushdata-bitcoin@1.0.1(transitive)
- Removedrandombytes@2.1.0(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedripemd160@2.0.2(transitive)
- Removedstring_decoder@1.3.0(transitive)
- Removedtiny-secp256k1@1.1.7(transitive)
- Removedtypeforce@1.18.0(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedvaruint-bitcoin@1.1.2(transitive)
- Removedwif@2.0.6(transitive)
Updated@stacks/common@^3.3.0