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

simple-js-ecdsa

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-js-ecdsa - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

2

package.json
{
"name": "simple-js-ecdsa",
"version": "1.2.0",
"version": "1.3.0",
"description": "easy and light weight ecdsa implementation",

@@ -5,0 +5,0 @@ "main": "./src/index.js",

@@ -5,25 +5,25 @@ # simple-js-ecdsa

creating a new wallet
creating a new identity
```
let wallet = Wallet.new()
let identity = Identity.new()
```
opening an existing wallet using a private key
opening an existing identity using a private key
```
Wallet.fromKey(<private number>)
Identity.fromKey(<private number>)
```
opening a wallet using a wif
opening a identity using a wif
```
Wallet.fromWif(<private wif>)
Identity.fromWif(<private wif>)
```
retrievable items in a wallet
retrievable items in a identity
```
wallet.key
wallet.sec1Compressed
wallet.sec1Uncompressed
wallet.wif
wallet.address
wallet.compressAddress
identity.key
identity.sec1Compressed
identity.sec1Uncompressed
identity.wif
identity.address
identity.compressAddress
```

@@ -33,3 +33,3 @@

```
const signature = wallet.sign(message)
const signature = identity.sign(message)
```

@@ -39,3 +39,3 @@

```
wallet.verify(message, signature)
identity.verify(message, signature)
```

@@ -45,3 +45,3 @@

```
const signature = wallet.bip66Sign(message)
const signature = identity.bip66Sign(message)
```

@@ -51,3 +51,3 @@

```
wallet.verifyBip66(message, signature)
identity.verifyBip66(message, signature)
```

@@ -54,0 +54,0 @@

@@ -1,7 +0,165 @@

const ECDSA = require('./ecdsa.js')
const Wallet = require('./wallet.js')
const bigInt = require('big-integer')
const base58 = require('bs58')
const crypto = require('crypto')
const secp256k1 = require('./secp256k1.js')
module.exports = {
ECDSA: ECDSA,
Wallet: Wallet,
}
let hex = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15 }
const sha256 = require('./sha256.js')
const ripemd160 = data => crypto.createHash('ripemd160').update(data, 'hex').digest('hex').toString()
const hexStringToBinaryString = s => {
s = s.toLowerCase()
const len = s.length;
var data = [];
for (let i = 0; i < len; i += 2) {
data[i / 2] = String.fromCharCode((hex[s[i]] << 4) + (hex[s[i + 1]]));
}
return data.join('');
}
const binSha256 = data => sha256(hexStringToBinaryString(data))
const binRipemd160 = data => ripemd160(data)
class Identity {
static new(curve = secp256k1) {
return Identity.fromKey(curve.modSet.random(), curve)
}
static fromKey(key, curve = secp256k1) {
const wallet = new Identity()
wallet.curve = curve
wallet.key = key
return wallet
}
static fromWif(wif, curve = secp256k1) {
const wallet = new Identity()
wallet.curve = curve
const hexWif = base58.decode(wif).toString('hex')
wallet.key = hexWif.substring(2, hexWif.length - 8)
if (wallet.wif !== wif) {
throw 'invalid wif'
}
return wallet
}
sign(message, k = this.curve.modSet.random()) {
k = bigInt(k, 16)
const e = bigInt(sha256(message), 16)
const da = bigInt(this.key, 16) // private key
const r = this.curve.multiply(this.curve.g, k)
const s1 = da.multiply(r.x).add(e)
const s = s1.multiply(k.modInv(this.curve.n)).mod(this.curve.n)
return {
r: bigInt(r.x).toString(16),
s: s.toString(16)
}
}
bip66Sign(message, k = this.curve.modSet.random()) {
let signature = this.sign(message, k)
const r = Buffer.from(signature.r, 'hex')
const s = Buffer.from(signature.s, 'hex')
const rl = r.length
const sl = s.length
signature = Buffer.allocUnsafe(6 + rl + sl)
signature[0] = 0x30
signature[1] = signature.length - 2
signature[2] = 0x02
signature[3] = rl
r.copy(signature, 4)
signature[4+rl] = 0x02
signature[5+rl] = sl
s.copy(signature, rl + 6)
if (this.verifyBip66(message, signature)) {
return signature.toString('hex')
}
console.warn('⚠️ k value was unusable, making new k. this will be fixed in a later version')
return this.bip66Sign(message)
}
verify(message, signature) {
const e = bigInt(sha256(message), 16)
const r = bigInt(signature.r, 16)
const s = bigInt(signature.s, 16)
const w = bigInt(s).modInv(this.curve.n)
const u1 = bigInt(e).multiply(w).mod(this.curve.n)
const u2 = r.multiply(w).mod(this.curve.n)
const p = this.curve.add(this.curve.multiply(this.curve.g, u1), this.curve.multiply(this.publicPoint, u2))
return p.x == r
}
verifyBip66(message, signature) {
signature = Buffer.from(signature, 'hex')
const lr = signature[3]
return this.verify(message, {
r: signature.slice(4, 4 + lr).toString('hex'),
s: signature.slice(6 + lr).toString('hex')
})
}
static fromAddress(address, curve = secp256k1) {
const wallet = new Identity()
wallet.curve = curve
wallet._address = address
return wallet
}
get wif() {
if (this._wif) {
return this._wif
}
const formatted = `80${this.key}`
const checksum = binSha256(binSha256(formatted)).substr(0, 8)
return this._wif = base58.encode(Buffer.from(`${formatted}${checksum}`, 'hex'))
}
get publicPoint() {
if (this._publicPoint) {
return this._publicPoint
}
return this._publicPoint = this.curve.multiply(this.curve.g, bigInt(this.key, 16))
}
get sec1Compressed() {
if (this._sec1Compressed) {
return this._sec1Compressed
}
let xStr = bigInt(this.publicPoint.x).toString(16)
while (xStr.length < 64) {
xStr = '0' + xStr
}
return this._sec1Compressed = `${bigInt(this.publicPoint.y).isOdd() ? '03' : '02'}${xStr}`
}
get sec1Uncompressed() {
if (this._sec1Uncompressed) {
return this._sec1Uncompressed
}
let yStr = bigInt(this.publicPoint.y).toString(16)
while (yStr.length < 64) {
yStr = '0' + yStr
}
let xStr = bigInt(this.publicPoint.x).toString(16)
while (xStr.length < 64) {
xStr = '0' + xStr
}
return this._sec1Uncompressed = `04${xStr}${yStr}`
}
get address() {
if (this._address) {
return this._address
}
const formatted = `00${binRipemd160(binSha256(this.sec1Uncompressed))}`
const checksum = binSha256(binSha256(formatted)).substr(0, 8)
return this._address = base58.encode(Buffer.from(`${formatted}${checksum}`, 'hex'))
}
get compressAddress() {
if (this._compressAddress) {
return this._compressAddress
}
const formatted = `00${binRipemd160(binSha256(this.sec1Compressed))}`
const checksum = binSha256(binSha256(formatted)).substr(0, 8)
return this._compressAddress = base58.encode(Buffer.from(`${formatted}${checksum}`, 'hex'))
}
}
module.exports = Identity
try {
const bigInt = require('big-integer')
const ecdsa = require('../src/index.js')
const Wallet = ecdsa.Wallet
const Identity = require('../src/index.js')
;(() => {

@@ -37,83 +36,90 @@ const privateToPublic = {

for (privateKey in privateToPublic) {
const wallet = Wallet.fromKey(privateKey)
if (privateToPublic[privateKey].pub !== wallet.sec1Compressed) {
throw `private key failed to make public ${privateKey} ${privateToPublic[privateKey].pub} ${wallet.address}`
const identity = Identity.fromKey(privateKey)
if (privateToPublic[privateKey].pub !== identity.sec1Compressed) {
throw `private key failed to make public ${privateKey} ${privateToPublic[privateKey].pub} ${identity.address}`
}
}
console.log('✅ retrieving identity from private key passed')
})()
const privateToPublic = {
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf':'1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm',
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreJQmdp3Y':'1KFLggHezq3kiAtpaKMeQPcnoWsXuZHRyn',
'5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V':'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM',
'5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh':'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a'
}
for (const private of Object.keys(privateToPublic)) {
let wallet = Wallet.fromWif(private)
// console.log('key', wallet.key)
// console.log('sec1 (compressed)',wallet.sec1Compressed)
// console.log('sec1 (uncompressed)',wallet.sec1Uncompressed)
// console.log('wif',wallet.wif)
// console.log('address',wallet.address)
// console.log('compressAddress',wallet.compressAddress)
if (wallet.address !== privateToPublic[private]) {
throw 'invalid public key generation '+privateToPublic[private]
;(()=>{
const privateToPublic = {
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf':'1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm',
'5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreJQmdp3Y':'1KFLggHezq3kiAtpaKMeQPcnoWsXuZHRyn',
'5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V':'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM',
'5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh':'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a'
}
}
for (const private of Object.keys(privateToPublic)) {
let identity = Identity.fromWif(private)
// console.log('key', identity.key)
// console.log('sec1 (compressed)',identity.sec1Compressed)
// console.log('sec1 (uncompressed)',identity.sec1Uncompressed)
// console.log('wif',identity.wif)
// console.log('address',identity.address)
// console.log('compressAddress',identity.compressAddress)
if (identity.address !== privateToPublic[private]) {
throw 'invalid public key generation '+privateToPublic[private]
}
}
console.log('✅ retrieving identity from wif passed')
})()
;(() => {
let wallet = Wallet.fromKey('82ef796afbce6e67bcb6bc44d922e5d2e664ebe118c0ed5b6ce3b481a638ec90')
const signature = wallet.sign('test', '2900c9abe4a9d00b2a4aa6663d8f4989c8cac35f4fe9b2c5b66e07a3903e1c3')
const identity = Identity.fromKey('82ef796afbce6e67bcb6bc44d922e5d2e664ebe118c0ed5b6ce3b481a638ec90')
const signature = identity.sign('test', '2900c9abe4a9d00b2a4aa6663d8f4989c8cac35f4fe9b2c5b66e07a3903e1c3')
const bip66Sig = identity.bip66Sign('test')
if (signature.r.toString(16) !== '85a44b824bda975b15ac77a3256c5d6f21c19b0412eb19333844fc2dbd25dbba') {
throw 'invalid signature r value'
}
// console.log('bip66',bip66.encode(new Buffer(signature.r.toString(16), 'hex'), new Buffer(signature.s.toString(16), 'hex')))
// if (signature.s.toString(16) !== '79a1e1e6c94d3cc0388d8659cf7e7fbc6d6e03a1a19446258d19b82071b95c7d') {
// throw 'invalid signature s value'
// }
if (wallet.verify('test', signature) !== true) {
if (identity.verify('test', signature) !== true) {
throw 'signing or verification failure'
}
if (wallet.verifyBip66('test', wallet.bip66Sign('test')) !== true) {
if (identity.verifyBip66('test', bip66Sig) !== true) {
throw 'bip 66 signing or verification failure'
}
if (wallet.verifyBip66(`${Math.random()}`, wallet.bip66Sign('test')) !== false) {
throw 'falsifiable bip 66 wallet verification'
if (identity.verifyBip66(`${Math.random()}`, bip66Sig) !== false) {
throw 'falsifiable bip 66 identity verification'
}
if (wallet.verify(`${Math.random()}`, signature) !== false) {
if (identity.verify(`${Math.random()}`, signature) !== false) {
throw 'falsifiable verification'
}
if (Wallet.new().verify('test', signature) !== false) {
throw 'falsifiable wallet verification'
if (Identity.new().verify('test', signature) !== false) {
throw 'falsifiable identity verification'
}
})()
let i = 0
while (i < 3) {
const message = `${Math.random()}`
let wallet = Wallet.new()
const signature = wallet.sign(message)
if (wallet.verify(message, signature) !== true) {
throw 'signing or verification failure'
;(()=>{
let i = 0
while (i < 2) {
const message = `${Math.random()}`
const identity = Identity.new()
const signature = identity.sign(message)
const bip66Sig = identity.bip66Sign(message)
if (identity.verify(message, signature) !== true) {
throw 'signing or verification failure'
}
if (identity.verifyBip66(message, bip66Sig) !== true) {
throw 'bip 66 signing or verification failure'
}
if (identity.verifyBip66(`${Math.random()}`, bip66Sig) !== false) {
throw 'falsifiable bip 66 identity verification'
}
if (identity.verify(`${Math.random()}`, signature) !== false) {
throw 'falsifiable verification'
}
if (Identity.new().verify(message, signature) !== false) {
throw 'falsifiable identity verification'
}
i++
}
if (wallet.verifyBip66(message, wallet.bip66Sign(message)) !== true) {
throw 'bip 66 signing or verification failure'
}
if (wallet.verifyBip66(`${Math.random()}`, wallet.bip66Sign(message)) !== false) {
throw 'falsifiable bip 66 wallet verification'
}
if (wallet.verify(`${Math.random()}`, signature) !== false) {
throw 'falsifiable verification'
}
if (Wallet.new().verify(message, signature) !== false) {
throw 'falsifiable wallet verification'
}
i++
}
console.log('✅ wallet tests passed')
console.log('✅ signing and verification passed')
})()
}
catch (e) {
console.log('⚠️ failed to test wallets', e)
console.log('⚠️ failed to test identitys', e)
throw e
}
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