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

cardano-crypto.js

Package Overview
Dependencies
Maintainers
1
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 4.0.2 to 4.1.0

utils/CborIndefiniteLengthArray.js

175

index.js
const bip39 = require('bip39-light')
const cbor = require('cbor')

@@ -8,2 +9,3 @@ const Module = require('./lib.js')

const pbkdf2 = require('./utils/pbkdf2')
const CborIndefiniteLengthArray = require('./utils/CborIndefiniteLengthArray')

@@ -54,2 +56,27 @@ const HARDENED_THRESHOLD = 0x80000000

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) {

@@ -494,2 +521,137 @@ validateBuffer(input)

async function decodePaperWalletMnemonic(paperWalletMnemonic) {
validatePaperWalletMnemonic(paperWalletMnemonic)
const paperWalletMnemonicAsList = paperWalletMnemonic.split(' ')
const mnemonicScrambledPart = paperWalletMnemonicAsList.slice(0, 18).join(' ')
const mnemonicPassphrasePart = paperWalletMnemonicAsList.slice(18, 27).join(' ')
const passphrase = await mnemonicToPaperWalletPassphrase(mnemonicPassphrasePart)
const unscrambledMnemonic = await paperWalletUnscrambleStrings(passphrase, mnemonicScrambledPart)
return unscrambledMnemonic
}
async function mnemonicToPaperWalletPassphrase(mnemonic, password) {
const mnemonicBuffer = Buffer.from(mnemonic, 'utf8')
const salt = `mnemonic${password || ''}`
const saltBuffer = Buffer.from(salt, 'utf8')
return (await pbkdf2(mnemonicBuffer, saltBuffer, 2048, 32, 'sha512')).toString('hex')
}
/* taken from https://github.com/input-output-hk/rust-cardano/blob/08796d9f100f417ff30549b297bd20b249f87809/cardano/src/paperwallet.rs */
async function paperWalletUnscrambleStrings(passphrase, mnemonic) {
const input = Buffer.from(bip39.mnemonicToEntropy(mnemonic), 'hex')
const saltLength = 8
if (saltLength >= input.length) {
throw Error('unscrambleStrings: Input is too short')
}
const outputLength = input.length - saltLength
const output = await pbkdf2(passphrase, input.slice(0, saltLength), 10000, outputLength, 'sha512')
for (let i = 0; i < outputLength; i++) {
output[i] = output[i] ^ input[saltLength + i]
}
return bip39.entropyToMnemonic(output)
}
async function xpubToHdPassphrase(xpub) {
validateBuffer(xpub, 64)
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 (derivationPath.length > 0 && derivationScheme === 1) {
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 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')
}
return {
derivationPath,
}
}
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) {
debugLog(err)
throw NamedError('AddressDecodingException', 'incorrect address or passphrase')
}
}
module.exports = {

@@ -500,11 +662,14 @@ derivePublic,

verify,
sha3_256,
chacha20poly1305Encrypt,
chacha20poly1305Decrypt,
blake2b,
walletSecretFromMnemonic,
decodePaperWalletMnemonic,
xpubToHdPassphrase,
packAddress,
unpackAddress,
cardanoMemoryCombine,
blake2b,
base58,
crc32,
scrypt,
_sha3_256: sha3_256,
_chacha20poly1305Decrypt: chacha20poly1305Decrypt,
_chacha20poly1305Encrypt: chacha20poly1305Encrypt,
}

5

package.json
{
"name": "cardano-crypto.js",
"version": "4.0.2",
"version": "4.1.0",
"description": "input-output-hk/cardano-crypto compiled to pure javascript using Emscripten",

@@ -29,4 +29,5 @@ "main": "index.js",

"dependencies": {
"bip39-light": "^1.0.7"
"bip39-light": "^1.0.7",
"cbor": "^4.1.1"
}
}

@@ -6,3 +6,3 @@ # cardano-crypto.js

compiled to pure javascript using Emscripten. This is a collection of cryptolibraries useful for doing Cardano cryptography, eliminating the need for many dependencies.
compiled to pure javascript using Emscripten. This is a collection of cryptolibraries and functions useful for working with Cardano cryptocurrency, eliminating the need for many dependencies.

@@ -49,7 +49,10 @@ # examples

* `Buffer derivePublic(Buffer parentExtPubKey, int index, int derivationScheme)`
* `Buffer decodePaperWalletMnemonic(string paperWalletMnemonic)`
* `Buffer xpubToHdPassphrase(Buffer xpub)`
* `string packAddress(Array[int] derivationPath, Buffer xpub, Buffer hdPassphrase, int derivationScheme)`
* `string unpackAddress(string address, Buffer hdPassphrase)`
* `Buffer blake2b(Buffer input, outputLen)`
* `Buffer sha3_256(Buffer input)`
* `Buffer chacha20poly1305Encrypt(Buffer input, Buffer key, Buffer nonce)`
* `Buffer chacha20poly1305Decrypt(Buffer input, Buffer key, Buffer nonce)`
* `Buffer cardanoMemoryCombine(Buffer input, String password)`
* `[base58](https://www.npmjs.com/package/base58)`
* `[scrypt](https://www.npmjs.com/package/scrypt-async)`

@@ -56,0 +59,0 @@ We encourage you to take a look `at test/index.js` to see how the functions above should be used.

@@ -20,2 +20,5 @@ var test = require('tape')

var sampleScryptDerivedKey = '5012b74fca8ec8a4a0a62ffdeeee959d'
var samplePaperWalletMnemonic =
'force usage medal chapter start myself odor ripple concert aspect wink melt afford lounge smart bulk way hazard burden type broken defense city announce reward same tumble'
var sampleDecodedPaperWalletMnemonic = 'swim average antenna there trap nice good stereo lion safe next brief'

@@ -135,3 +138,3 @@ test('wallet secret from mnemonic V1', async function(t) {

t.equals(
lib.sha3_256(message).toString('hex'),
lib._sha3_256(message).toString('hex'),
'98b05e27eab982f4d108694a5ab636d68cc898e4af98980516fe2560b13e53a9',

@@ -150,3 +153,3 @@ 'should properly compute sha3_256 hash'

t.equals(
lib.chacha20poly1305Encrypt(message, key, nonce, true).toString('hex'),
lib._chacha20poly1305Encrypt(message, key, nonce, true).toString('hex'),
expectedEncryptionResult.toString('hex'),

@@ -157,3 +160,3 @@ 'should properly encrypt with chacha20poly1305'

t.equals(
lib.chacha20poly1305Decrypt(expectedEncryptionResult, key, nonce, false).toString('hex'),
lib._chacha20poly1305Decrypt(expectedEncryptionResult, key, nonce, false).toString('hex'),
message.toString('hex'),

@@ -203,1 +206,10 @@ 'should properly decrypt with chacha20poly1305'

})
test('paper wallet mnemonic decoding', async function (t) {
t.plan(1)
t.equals(
await lib.decodePaperWalletMnemonic(samplePaperWalletMnemonic),
sampleDecodedPaperWalletMnemonic,
'should properly decode paper wallet mnemonic'
)
})
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