Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cardano-crypto.js

Package Overview
Dependencies
Maintainers
3
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cardano-crypto.js - npm Package Compare versions

Comparing version 5.3.5 to 5.3.6-rc.0

address.js

383

index.js

@@ -0,80 +1,15 @@

const {validateBuffer, validateDerivationIndex, validateDerivationScheme, validateMnemonic, validateArray, validateString, validatePaperWalletMnemonic} = require("./utils/validation")
const address = require("./address");
const crypto = require("./crypto-primitives")
const bech32 = require("bech32")
const bip39 = require('bip39')
const cbor = require('borc')
const Module = require('./lib.js')
const crc32 = require('./utils/crc32')
const base58 = require('./utils/base58')
const scrypt = require('./utils/scrypt-async')
const pbkdf2 = require('./utils/pbkdf2')
const CborIndefiniteLengthArray = require('./utils/CborIndefiniteLengthArray')
const HARDENED_THRESHOLD = 0x80000000
function validateDerivationScheme(input) {
if (input !== 1 && input !== 2) {
throw new Error('invalid derivation scheme!')
}
}
function validateBuffer(input, expectedLength) {
if (!Buffer.isBuffer(input)) {
throw new Error('not buffer!')
}
if (expectedLength && input.length !== expectedLength) {
throw new Error('Invalid buffer length')
}
}
function validateArray(input) {
if (typeof input !== typeof []) {
throw new Error('not an array!')
}
}
function validateDerivationIndex(input) {
if (!Number.isInteger(input)) {
throw new Error('invalid derivation index!')
}
}
function validateString(input) {
if (typeof input !== typeof 'aa') {
throw new Error('not a string!')
}
}
function validateMnemonic(input) {
if (!bip39.validateMnemonic(input)) {
const e = new Error('Invalid or unsupported mnemonic format:')
e.name = 'InvalidArgumentException'
throw e
}
}
function validateMnemonicWords(input) {
const wordlist = bip39.wordlists.EN
const words = input.split(' ')
const valid = words.reduce((result, word) => {
return result && wordlist.indexOf(word) !== -1
}, true)
if (!valid) {
throw new Error('Invalid mnemonic words')
}
}
function validatePaperWalletMnemonic(input) {
validateMnemonicWords(input)
const mnemonicLength = input.split(' ').length
if (mnemonicLength !== 27) {
throw Error(
`Paper Wallet Mnemonic must be 27 words, got ${mnemonicLength} instead`
)
}
}
function cborEncodeBuffer(input) {

@@ -166,4 +101,4 @@ validateBuffer(input)

const entropy = Buffer.from(bip39.mnemonicToEntropy(mnemonic), 'hex')
return cborEncodeBuffer(blake2b(cborEncodeBuffer(entropy), 32))
return cborEncodeBuffer(crypto.blake2b(cborEncodeBuffer(entropy), 32))
}

@@ -175,3 +110,3 @@

try {
const digest = hmac_sha512(seed, [Buffer.from(`Root Seed Chain ${i}`, 'ascii')])
const digest = crypto.hmac_sha512(seed, [Buffer.from(`Root Seed Chain ${i}`, 'ascii')])
const tempSeed = digest.slice(0, 32)

@@ -326,83 +261,2 @@ const chainCode = digest.slice(32, 64)

function blake2b(input, outputLen) {
validateBuffer(input)
const inputLen = input.length
const inputArrPtr = Module._malloc(inputLen)
const inputArr = new Uint8Array(Module.HEAPU8.buffer, inputArrPtr, inputLen)
const outputArrPtr = Module._malloc(outputLen)
const outputArr = new Uint8Array(Module.HEAPU8.buffer, outputArrPtr, outputLen)
inputArr.set(input)
Module._emscripten_blake2b(inputArrPtr, inputLen, outputArrPtr, outputLen)
Module._free(inputArrPtr)
Module._free(outputArrPtr)
return Buffer.from(outputArr)
}
function sha3_256(input) {
validateBuffer(input)
const inputLen = input.length
const inputArrPtr = Module._malloc(inputLen)
const inputArr = new Uint8Array(Module.HEAPU8.buffer, inputArrPtr, inputLen)
const outputLen = 32
const outputArrPtr = Module._malloc(outputLen)
const outputArr = new Uint8Array(Module.HEAPU8.buffer, outputArrPtr, outputLen)
inputArr.set(input)
Module._emscripten_sha3_256(inputArrPtr, inputLen, outputArrPtr)
Module._free(inputArrPtr)
Module._free(outputArrPtr)
return Buffer.from(outputArr)
}
function hmac_sha512(initKey, inputs) {
validateBuffer(initKey)
validateArray(inputs)
inputs.map(validateBuffer)
const ctxLen = Module._emscripten_size_of_hmac_sha512_ctx()
const ctxArrPtr = Module._malloc(ctxLen)
const ctxArr = new Uint8Array(Module.HEAPU8.buffer, ctxArrPtr, ctxLen)
const initKeyLen = initKey.length
const initKeyArrPtr = Module._malloc(initKeyLen)
const initKeyArr = new Uint8Array(Module.HEAPU8.buffer, initKeyArrPtr, initKeyLen)
const outputLen = 64
const outputArrPtr = Module._malloc(outputLen)
const outputArr = new Uint8Array(Module.HEAPU8.buffer, outputArrPtr, outputLen)
initKeyArr.set(initKey)
Module._emscripten_hmac_sha512_init(ctxArrPtr, initKeyArrPtr, initKeyLen)
for (let i = 0; i < inputs.length; i++) {
const inputLen = inputs[i].length
const inputArrPtr = Module._malloc(inputLen)
const inputArr = new Uint8Array(Module.HEAPU8.buffer, inputArrPtr, inputLen)
inputArr.set(inputs[i])
Module._emscripten_hmac_sha512_update(ctxArrPtr, inputArrPtr, inputLen)
Module._free(inputArrPtr)
}
Module._emscripten_hmac_sha512_final(ctxArrPtr, outputArrPtr)
Module._free(initKeyArrPtr)
Module._free(ctxArrPtr)
Module._free(outputArrPtr)
return Buffer.from(outputArr)
}
function cardanoMemoryCombine(input, password) {

@@ -416,3 +270,3 @@ validateString(password)

const transformedPassword = blake2b(Buffer.from(password, 'utf-8'), 32)
const transformedPassword = crypto.blake2b(Buffer.from(password, 'utf-8'), 32)
const transformedPasswordLen = transformedPassword.length

@@ -441,91 +295,2 @@ const transformedPasswordArrPtr = Module._malloc(transformedPasswordLen)

function chacha20poly1305Encrypt(input, key, nonce) {
validateBuffer(input)
validateBuffer(key, 32)
validateBuffer(nonce, 12)
const inputLen = input.length
const inputArrPtr = Module._malloc(inputLen)
const inputArr = new Uint8Array(Module.HEAPU8.buffer, inputArrPtr, inputLen)
const keyLen = key.length
const keyArrPtr = Module._malloc(keyLen)
const keyArr = new Uint8Array(Module.HEAPU8.buffer, keyArrPtr, keyLen)
const nonceLen = nonce.length
const nonceArrPtr = Module._malloc(nonceLen)
const nonceArr = new Uint8Array(Module.HEAPU8.buffer, nonceArrPtr, nonceLen)
const tagLen = 16
const outputLen = inputLen + tagLen
const outputArrPtr = Module._malloc(outputLen)
const outputArr = new Uint8Array(Module.HEAPU8.buffer, outputArrPtr, outputLen)
inputArr.set(input)
keyArr.set(key)
nonceArr.set(nonce)
const resultCode = Module._emscripten_chacha20poly1305_enc(keyArrPtr, nonceArrPtr, inputArrPtr, inputLen, outputArrPtr, outputArrPtr + inputLen, tagLen, 1)
Module._free(inputArrPtr)
Module._free(keyArrPtr)
Module._free(nonceArrPtr)
Module._free(outputArrPtr)
if (resultCode !== 0) {
throw Error('chacha20poly1305 encryption has failed!')
}
return Buffer.from(outputArr)
}
function chacha20poly1305Decrypt(input, key, nonce) {
validateBuffer(input)
validateBuffer(key, 32)
validateBuffer(nonce, 12)
// extract tag from input
const tagLen = 16
const tag = input.slice(input.length - tagLen, input.length)
input = input.slice(0, input.length - tagLen)
const inputLen = input.length
const inputArrPtr = Module._malloc(inputLen)
const inputArr = new Uint8Array(Module.HEAPU8.buffer, inputArrPtr, inputLen)
const tagArrPtr = Module._malloc(tagLen)
const tagArr = new Uint8Array(Module.HEAPU8.buffer, tagArrPtr, tagLen)
const keyLen = key.length
const keyArrPtr = Module._malloc(keyLen)
const keyArr = new Uint8Array(Module.HEAPU8.buffer, keyArrPtr, keyLen)
const nonceLen = nonce.length
const nonceArrPtr = Module._malloc(nonceLen)
const nonceArr = new Uint8Array(Module.HEAPU8.buffer, nonceArrPtr, nonceLen)
const outputLen = inputLen
const outputArrPtr = Module._malloc(outputLen)
const outputArr = new Uint8Array(Module.HEAPU8.buffer, outputArrPtr, outputLen)
inputArr.set(input)
tagArr.set(tag)
keyArr.set(key)
nonceArr.set(nonce)
const resultCode = Module._emscripten_chacha20poly1305_enc(keyArrPtr, nonceArrPtr, inputArrPtr, inputLen, outputArrPtr, tagArrPtr, tagLen, 0)
Module._free(inputArrPtr)
Module._free(keyArrPtr)
Module._free(nonceArrPtr)
Module._free(outputArrPtr)
Module._free(tagArrPtr)
if (resultCode !== 0) {
throw Error('chacha20poly1305 decryption has failed!')
}
return Buffer.from(outputArr)
}
async function decodePaperWalletMnemonic(paperWalletMnemonic) {

@@ -575,111 +340,19 @@ validatePaperWalletMnemonic(paperWalletMnemonic)

return pbkdf2(xpub, 'address-hashing', 500, 32, 'sha512')
return pbkdf2(xpub, 'address-hashing', 500, 32, 'sha512')
}
function packAddress(derivationPath, xpub, hdPassphrase, derivationScheme) {
validateBuffer(xpub, 64)
validateDerivationScheme(derivationScheme)
if (derivationScheme === 1) {
validateArray(derivationPath)
validateBuffer(hdPassphrase, 32)
}
let addressPayload, addressAttributes
if (derivationScheme === 1 && derivationPath.length > 0) {
addressPayload = encryptDerivationPath(derivationPath, hdPassphrase)
addressAttributes = new Map([[1, cbor.encode(addressPayload)]])
} else {
addressPayload = Buffer.from([])
addressAttributes = new Map()
}
const addressRoot = getAddressHash([
0,
[0, xpub],
addressPayload.length > 0 ? new Map([[1, cbor.encode(addressPayload)]]) : new Map(),
])
const addressType = 0 // Public key address
const addressData = [addressRoot, addressAttributes, addressType]
const addressDataEncoded = cbor.encode(addressData)
return base58.encode(
cbor.encode([new cbor.Tagged(24, addressDataEncoded), crc32(addressDataEncoded)])
)
function bech32Encode(prefix, data) {
const words = bech32.toWords(data)
// we need longer than default length for privkeys and 1000 should suffice
return bech32.encode(prefix, words, 1000)
}
function unpackAddress(address, hdPassphrase) {
// we decode the address from the base58 string
// and then we strip the 24 CBOR data tags (the "[0].value" part)
const addressAsBuffer = cbor.decode(base58.decode(address))[0].value
const addressData = cbor.decode(addressAsBuffer)
const attributes = addressData[1]
const payload = cbor.decode(attributes.get(1))
let derivationPath
try {
derivationPath = decryptDerivationPath(payload, hdPassphrase)
} catch (e) {
throw new Error('Unable to get derivation path from address')
}
if (derivationPath && derivationPath.length > 2) {
throw Error('Invalid derivation path length, should be at most 2')
}
function bech32Decode(str){
const tmp = bech32.decode(str, 1000)
return {
derivationPath,
prefix: tmp.prefix,
data: Buffer.from(bech32.fromWords(tmp.words)),
}
}
function isValidAddress(address) {
try {
// we decode the address from the base58 string
const addressAsArray = cbor.decode(base58.decode(address))
// we strip the 24 CBOR data taga by taking the "value" attribute from the "Tagged" object
const addressDataEncoded = addressAsArray[0].value
const crc32Checksum = addressAsArray[1]
if (crc32Checksum !== crc32(addressDataEncoded)) {
return false
}
} catch (e) {
return false
}
return true
}
function getAddressHash(input) {
// eslint-disable-next-line camelcase
const firstHash = sha3_256(cbor.encode(input))
return blake2b(firstHash, 28)
}
function encryptDerivationPath(derivationPath, hdPassphrase) {
const serializedDerivationPath = cbor.encode(new CborIndefiniteLengthArray(derivationPath))
return chacha20poly1305Encrypt(
serializedDerivationPath,
hdPassphrase,
Buffer.from('serokellfore')
)
}
function decryptDerivationPath(addressPayload, hdPassphrase) {
const decipheredDerivationPath = chacha20poly1305Decrypt(
addressPayload,
hdPassphrase,
Buffer.from('serokellfore')
)
try {
return cbor.decode(Buffer.from(decipheredDerivationPath))
} catch (err) {
throw new Error('incorrect address or passphrase')
}
}
module.exports = {

@@ -693,8 +366,14 @@ derivePublic,

xpubToHdPassphrase,
packAddress,
unpackAddress,
isValidAddress,
packBootstrapAddress: address.packBootstrapAddress,
packBaseAddress: address.packBaseAddress,
packPointerAddress: address.packPointerAddress,
packEnterpriseAddress: address.packEnterpriseAddress,
getAddressInfo: address.getAddressInfo,
unpackAddress: address.unpackAddress,
isValidAddress: address.isValidAddress,
cardanoMemoryCombine,
blake2b,
blake2b: crypto.blake2b,
base58,
bech32_encode: bech32Encode,
bech32_decode: bech32Decode,
scrypt,

@@ -706,5 +385,5 @@ toPublic,

_seedToKeypairV2: seedToKeypairV2,
_sha3_256: sha3_256,
_chacha20poly1305Decrypt: chacha20poly1305Decrypt,
_chacha20poly1305Encrypt: chacha20poly1305Encrypt,
_sha3_256: crypto.sha3_256,
_chacha20poly1305Decrypt: crypto.chacha20poly1305Decrypt,
_chacha20poly1305Encrypt: crypto.chacha20poly1305Encrypt,
}
{
"name": "cardano-crypto.js",
"version": "5.3.5",
"version": "5.3.6-rc.0",
"description": "input-output-hk/cardano-crypto compiled to pure javascript using Emscripten",

@@ -29,2 +29,3 @@ "main": "index.js",

"dependencies": {
"bech32": "^1.1.4",
"bip39": "^3.0.2",

@@ -31,0 +32,0 @@ "borc": "^2.1.1",

@@ -51,3 +51,7 @@ # cardano-crypto.js

* `Buffer xpubToHdPassphrase(Buffer xpub)`
* `string packAddress(Array[int] derivationPath, Buffer xpub, Buffer hdPassphrase, int derivationScheme)`
* `Buffer packBootstrapAddress(Array[int] derivationPath, Buffer xpub, Buffer hdPassphrase, int derivationScheme)`
* `Buffer packBaseAddress(Buffer pubKey, Buffer stakePubKey, int addressTypeId, int networkId, Bool isStakeHash = false)`
* `Buffer packPointerAddress(Buffer pubKey, Object pointer, int addressTypeId, int networkId)`
* `Buffer packEnterpriseAddress(Buffer pubKey, int addressTypeId, int networkId)`
* `Object getAddressInfo(Buffer address)`
* `string unpackAddress(string address, Buffer hdPassphrase)`

@@ -57,2 +61,4 @@ * `Bool isValidAddress(string address)`

* `Buffer cardanoMemoryCombine(Buffer input, String password)`
* `string bech32Encode(string prefix, Buffer data)`
* `Object bech32Decode(string address)`
* `[base58](https://www.npmjs.com/package/base58)`

@@ -59,0 +65,0 @@ * `[scrypt](https://www.npmjs.com/package/scrypt-async)`

@@ -244,3 +244,3 @@ const test = require('tape')

t.equals(
lib.packAddress(
lib.base58.encode(lib.packBootstrapAddress(
derivationPath,

@@ -250,3 +250,3 @@ sampleExtendedPublicKey,

1
),
)),
expectedV1Address,

@@ -264,3 +264,3 @@ 'should properly pack V1 address'

t.equals(
lib.packAddress(
lib.base58.encode(lib.packBootstrapAddress(
derivationPath,

@@ -270,3 +270,3 @@ sampleExtendedPublicKey,

2
),
)),
'Ae2tdPwUPEZCxt4UV1Uj2AMMRvg5pYPypqZowVptz3GYpK4pkcvn3EjkuNH',

@@ -277,2 +277,59 @@ 'should properly pack V2 address'

test('shelley addresses', (t) => {
t.plan(5)
let pubKeyCardanoTestvector = Buffer.from('73fea80d424276ad0978d4fe5310e8bc2d485f5f6bb3bf87612989f112ad5a7d', 'hex')
let stakeKey = Buffer.from('2c041c9c6a676ac54d25e2fdce44c56581e316ae43adc4c7bf17f23214d8d892', 'hex')
t.equals(
lib.packBaseAddress(pubKeyCardanoTestvector, stakeKey, 0, 3).toString('hex'),
'039493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e32c728d3861e164cab28cb8f006448139c8f1740ffb8e7aa9e5232dc',
'should properly derive base address'
)
let pubKeyTrezorTestvector = Buffer.from('7dbfba606303655d426f55cca9f77b1b9e2bca0ae69ca2ba7749d7bfc5303260', 'hex')
let stakeHash = Buffer.from('122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', 'hex')
t.equals(
lib.packBaseAddress(pubKeyTrezorTestvector, stakeHash, 0, 3, true).toString('hex'),
'03eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb9122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277',
'should properly derive base address with unowned staking key hash'
)
t.equals(
lib.packEnterpriseAddress(pubKeyCardanoTestvector, 6, 0).toString('hex'),
'609493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e',
'should properly derive enterprise address'
)
let pointer = {blockIndex: 24157, txIndex: 177, certificateIndex: 42}
t.equals(
lib.packPointerAddress(pubKeyCardanoTestvector, pointer, 4, 3).toString('hex'),
'439493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e81bc5d81312a',
'should properly derive pointer address'
)
t.equals(
JSON.stringify(lib.getAddressInfo(
Buffer.from('439493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e81bc5d81312a', 'hex')
)),
JSON.stringify({
addressType: 4, networkId: 3
}),
'should properly decode address header'
)
})
test('bech32', (t) => {
t.plan(2)
let addressBech = 'addr1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwqcyl47r'
let addressBuffer = Buffer.from('009493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e32c728d3861e164cab28cb8f006448139c8f1740ffb8e7aa9e5232dc', 'hex')
t.equals(
lib.bech32_encode('addr', addressBuffer),
addressBech,
'should properly encode bech32 address'
)
t.equals(
lib.bech32_decode(addressBech)
.data.toString('hex'),
addressBuffer.toString('hex'),
"should properly decode bech32 address"
)
})
test('proper error handling by the library', (t) => {

@@ -279,0 +336,0 @@ // to avoid accidentally injecting unhandledRejection handler with Emscripten

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc