ecdsa: moved all signature encoding to ECSignature
This commit is contained in:
parent
c5252fc509
commit
eb3d9a25f7
9 changed files with 350 additions and 297 deletions
105
src/ecdsa.js
105
src/ecdsa.js
|
@ -2,6 +2,7 @@ var assert = require('assert')
|
||||||
var crypto = require('./crypto')
|
var crypto = require('./crypto')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
var ECSignature = require('./ecsignature')
|
||||||
var Point = require('ecurve').Point
|
var Point = require('ecurve').Point
|
||||||
|
|
||||||
function deterministicGenerateK(curve, hash, d) {
|
function deterministicGenerateK(curve, hash, d) {
|
||||||
|
@ -51,7 +52,7 @@ function sign(curve, hash, d) {
|
||||||
s = n.subtract(s)
|
s = n.subtract(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {r: r, s: s}
|
return new ECSignature(r, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
function verify(curve, hash, signature, Q) {
|
function verify(curve, hash, signature, Q) {
|
||||||
|
@ -81,102 +82,6 @@ function verifyRaw(curve, e, signature, Q) {
|
||||||
return v.equals(r)
|
return v.equals(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize a signature into DER format.
|
|
||||||
*
|
|
||||||
* Takes two BigIntegers representing r and s and returns a byte array.
|
|
||||||
*/
|
|
||||||
function serializeSig(signature) {
|
|
||||||
var rBa = signature.r.toDERInteger()
|
|
||||||
var sBa = signature.s.toDERInteger()
|
|
||||||
|
|
||||||
var sequence = []
|
|
||||||
sequence.push(0x02) // INTEGER
|
|
||||||
sequence.push(rBa.length)
|
|
||||||
sequence = sequence.concat(rBa)
|
|
||||||
|
|
||||||
sequence.push(0x02) // INTEGER
|
|
||||||
sequence.push(sBa.length)
|
|
||||||
sequence = sequence.concat(sBa)
|
|
||||||
|
|
||||||
sequence.unshift(sequence.length)
|
|
||||||
sequence.unshift(0x30) // SEQUENCE
|
|
||||||
|
|
||||||
return new Buffer(sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a buffer containing a DER-encoded signature.
|
|
||||||
*
|
|
||||||
* This function will return an object of the form:
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* r: BigInteger,
|
|
||||||
* s: BigInteger
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
function parseSig(buffer) {
|
|
||||||
assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence')
|
|
||||||
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
|
|
||||||
|
|
||||||
assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer')
|
|
||||||
var rLen = buffer.readUInt8(3)
|
|
||||||
var rB = buffer.slice(4, 4 + rLen)
|
|
||||||
|
|
||||||
var offset = 4 + rLen
|
|
||||||
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)')
|
|
||||||
var sLen = buffer.readUInt8(1 + offset)
|
|
||||||
var sB = buffer.slice(2 + offset)
|
|
||||||
offset += 2 + sLen
|
|
||||||
|
|
||||||
assert.equal(offset, buffer.length, 'Invalid DER encoding')
|
|
||||||
|
|
||||||
return {
|
|
||||||
r: BigInteger.fromDERInteger(rB),
|
|
||||||
s: BigInteger.fromDERInteger(sB)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function serializeSigCompact(signature, i, compressed) {
|
|
||||||
if (compressed) {
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 27
|
|
||||||
|
|
||||||
var buffer = new Buffer(65)
|
|
||||||
buffer.writeUInt8(i, 0)
|
|
||||||
|
|
||||||
signature.r.toBuffer(32).copy(buffer, 1)
|
|
||||||
signature.s.toBuffer(32).copy(buffer, 33)
|
|
||||||
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseSigCompact(buffer) {
|
|
||||||
assert.equal(buffer.length, 65, 'Invalid signature length')
|
|
||||||
var i = buffer.readUInt8(0) - 27
|
|
||||||
|
|
||||||
// At most 3 bits
|
|
||||||
assert.equal(i, i & 7, 'Invalid signature parameter')
|
|
||||||
var compressed = !!(i & 4)
|
|
||||||
|
|
||||||
// Recovery param only
|
|
||||||
i = i & 3
|
|
||||||
|
|
||||||
var r = BigInteger.fromBuffer(buffer.slice(1, 33))
|
|
||||||
var s = BigInteger.fromBuffer(buffer.slice(33))
|
|
||||||
|
|
||||||
return {
|
|
||||||
signature: {
|
|
||||||
r: r,
|
|
||||||
s: s
|
|
||||||
},
|
|
||||||
i: i,
|
|
||||||
compressed: compressed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recover a public key from a signature.
|
* Recover a public key from a signature.
|
||||||
*
|
*
|
||||||
|
@ -269,9 +174,5 @@ module.exports = {
|
||||||
recoverPubKey: recoverPubKey,
|
recoverPubKey: recoverPubKey,
|
||||||
sign: sign,
|
sign: sign,
|
||||||
verify: verify,
|
verify: verify,
|
||||||
verifyRaw: verifyRaw,
|
verifyRaw: verifyRaw
|
||||||
serializeSig: serializeSig,
|
|
||||||
parseSig: parseSig,
|
|
||||||
serializeSigCompact: serializeSigCompact,
|
|
||||||
parseSigCompact: parseSigCompact
|
|
||||||
}
|
}
|
||||||
|
|
102
src/ecsignature.js
Normal file
102
src/ecsignature.js
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
var assert = require('assert')
|
||||||
|
|
||||||
|
var BigInteger = require('bigi')
|
||||||
|
|
||||||
|
function ECSignature(r, s) {
|
||||||
|
assert(r instanceof BigInteger, 'Expected BigInteger, got ' + r)
|
||||||
|
assert(s instanceof BigInteger, 'Expected BigInteger, got ' + s)
|
||||||
|
this.r = r
|
||||||
|
this.s = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import operations
|
||||||
|
ECSignature.fromCompact = function(buffer) {
|
||||||
|
assert.equal(buffer.length, 65, 'Invalid signature length')
|
||||||
|
var i = buffer.readUInt8(0) - 27
|
||||||
|
|
||||||
|
// At most 3 bits
|
||||||
|
assert.equal(i, i & 7, 'Invalid signature parameter')
|
||||||
|
var compressed = !!(i & 4)
|
||||||
|
|
||||||
|
// Recovery param only
|
||||||
|
i = i & 3
|
||||||
|
|
||||||
|
var r = BigInteger.fromBuffer(buffer.slice(1, 33))
|
||||||
|
var s = BigInteger.fromBuffer(buffer.slice(33))
|
||||||
|
|
||||||
|
return {
|
||||||
|
compressed: compressed,
|
||||||
|
i: i,
|
||||||
|
signature: new ECSignature(r, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ECSignature.fromDER = function(buffer) {
|
||||||
|
assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence')
|
||||||
|
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length')
|
||||||
|
|
||||||
|
assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer')
|
||||||
|
var rLen = buffer.readUInt8(3)
|
||||||
|
var rB = buffer.slice(4, 4 + rLen)
|
||||||
|
|
||||||
|
var offset = 4 + rLen
|
||||||
|
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)')
|
||||||
|
var sLen = buffer.readUInt8(1 + offset)
|
||||||
|
var sB = buffer.slice(2 + offset)
|
||||||
|
offset += 2 + sLen
|
||||||
|
|
||||||
|
assert.equal(offset, buffer.length, 'Invalid DER encoding')
|
||||||
|
var r = BigInteger.fromDERInteger(rB)
|
||||||
|
var s = BigInteger.fromDERInteger(sB)
|
||||||
|
|
||||||
|
return new ECSignature(r, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
ECSignature.fromScriptSignature = function(buffer) {
|
||||||
|
return {
|
||||||
|
signature: ECSignature.fromDER(buffer.slice(0, -1)),
|
||||||
|
hashType: buffer.readUInt8(buffer.length - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export operations
|
||||||
|
ECSignature.prototype.toCompact = function(i, compressed) {
|
||||||
|
if (compressed) i += 4
|
||||||
|
i += 27
|
||||||
|
|
||||||
|
var buffer = new Buffer(65)
|
||||||
|
buffer.writeUInt8(i, 0)
|
||||||
|
|
||||||
|
this.r.toBuffer(32).copy(buffer, 1)
|
||||||
|
this.s.toBuffer(32).copy(buffer, 33)
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
ECSignature.prototype.toDER = function() {
|
||||||
|
var rBa = this.r.toDERInteger()
|
||||||
|
var sBa = this.s.toDERInteger()
|
||||||
|
|
||||||
|
var sequence = []
|
||||||
|
sequence.push(0x02) // INTEGER
|
||||||
|
sequence.push(rBa.length)
|
||||||
|
sequence = sequence.concat(rBa)
|
||||||
|
|
||||||
|
sequence.push(0x02) // INTEGER
|
||||||
|
sequence.push(sBa.length)
|
||||||
|
sequence = sequence.concat(sBa)
|
||||||
|
|
||||||
|
sequence.unshift(sequence.length)
|
||||||
|
sequence.unshift(0x30) // SEQUENCE
|
||||||
|
|
||||||
|
return new Buffer(sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
ECSignature.prototype.toScriptSignature = function(hashType) {
|
||||||
|
var hashTypeBuffer = new Buffer(1)
|
||||||
|
hashTypeBuffer.writeUInt8(hashType, 0)
|
||||||
|
|
||||||
|
return Buffer.concat([this.toDER(), hashTypeBuffer])
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ECSignature
|
|
@ -8,6 +8,7 @@ module.exports = {
|
||||||
ecdsa: require('./ecdsa'),
|
ecdsa: require('./ecdsa'),
|
||||||
ECKey: require('./eckey'),
|
ECKey: require('./eckey'),
|
||||||
ECPubKey: require('./ecpubkey'),
|
ECPubKey: require('./ecpubkey'),
|
||||||
|
ECSignature: require('./ecsignature'),
|
||||||
Message: require('./message'),
|
Message: require('./message'),
|
||||||
opcodes: require('./opcodes'),
|
opcodes: require('./opcodes'),
|
||||||
HDNode: require('./hdnode'),
|
HDNode: require('./hdnode'),
|
||||||
|
|
|
@ -8,6 +8,7 @@ var networks = require('./networks')
|
||||||
|
|
||||||
var Address = require('./address')
|
var Address = require('./address')
|
||||||
var ECPubKey = require('./ecpubkey')
|
var ECPubKey = require('./ecpubkey')
|
||||||
|
var ECSignature = require('./ecsignature')
|
||||||
|
|
||||||
var ecurve = require('ecurve')
|
var ecurve = require('ecurve')
|
||||||
var ecparams = ecurve.getCurveByName('secp256k1')
|
var ecparams = ecurve.getCurveByName('secp256k1')
|
||||||
|
@ -18,32 +19,30 @@ function magicHash(message, network) {
|
||||||
var lengthBuffer = new Buffer(bufferutils.varIntSize(messageBuffer.length))
|
var lengthBuffer = new Buffer(bufferutils.varIntSize(messageBuffer.length))
|
||||||
bufferutils.writeVarInt(lengthBuffer, messageBuffer.length, 0)
|
bufferutils.writeVarInt(lengthBuffer, messageBuffer.length, 0)
|
||||||
|
|
||||||
var buffer = Buffer.concat([
|
var buffer = Buffer.concat([magicPrefix, lengthBuffer, messageBuffer])
|
||||||
magicPrefix, lengthBuffer, messageBuffer
|
|
||||||
])
|
|
||||||
return crypto.hash256(buffer)
|
return crypto.hash256(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
function sign(key, message, network) {
|
function sign(privKey, message, network) {
|
||||||
network = network || networks.bitcoin
|
network = network || networks.bitcoin
|
||||||
|
|
||||||
var hash = magicHash(message, network)
|
var hash = magicHash(message, network)
|
||||||
var signature = key.sign(hash)
|
var signature = privKey.sign(hash)
|
||||||
var e = BigInteger.fromBuffer(hash)
|
var e = BigInteger.fromBuffer(hash)
|
||||||
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, key.pub.Q)
|
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, privKey.pub.Q)
|
||||||
|
|
||||||
return ecdsa.serializeSigCompact(signature, i, key.pub.compressed)
|
return signature.toCompact(i, privKey.pub.compressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: network could be implied from address
|
// TODO: network could be implied from address
|
||||||
function verify(address, compactSig, message, network) {
|
function verify(address, signatureBuffer, message, network) {
|
||||||
if (address instanceof Address) {
|
if (address instanceof Address) {
|
||||||
address = address.toString()
|
address = address.toString()
|
||||||
}
|
}
|
||||||
network = network || networks.bitcoin
|
network = network || networks.bitcoin
|
||||||
|
|
||||||
var hash = magicHash(message, network)
|
var hash = magicHash(message, network)
|
||||||
var parsed = ecdsa.parseSigCompact(compactSig)
|
var parsed = ECSignature.fromCompact(signatureBuffer)
|
||||||
var e = BigInteger.fromBuffer(hash)
|
var e = BigInteger.fromBuffer(hash)
|
||||||
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)
|
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var bufferutils = require('./bufferutils')
|
var bufferutils = require('./bufferutils')
|
||||||
var crypto = require('./crypto')
|
var crypto = require('./crypto')
|
||||||
var ecdsa = require('./ecdsa')
|
|
||||||
var opcodes = require('./opcodes')
|
var opcodes = require('./opcodes')
|
||||||
var scripts = require('./scripts')
|
var scripts = require('./scripts')
|
||||||
|
|
||||||
var Address = require('./address')
|
var Address = require('./address')
|
||||||
var ECKey = require('./eckey')
|
var ECKey = require('./eckey')
|
||||||
|
var ECSignature = require('./ecsignature')
|
||||||
var Script = require('./script')
|
var Script = require('./script')
|
||||||
|
|
||||||
var DEFAULT_SEQUENCE = 0xffffffff
|
var DEFAULT_SEQUENCE = 0xffffffff
|
||||||
|
@ -301,16 +301,11 @@ Transaction.prototype.sign = function(index, privKey, hashType) {
|
||||||
|
|
||||||
Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) {
|
Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) {
|
||||||
hashType = hashType || SIGHASH_ALL
|
hashType = hashType || SIGHASH_ALL
|
||||||
assert(privKey instanceof ECKey, 'Expected ECKey, got ' + privKey)
|
|
||||||
|
|
||||||
var hash = this.hashForSignature(prevOutScript, index, hashType)
|
var hash = this.hashForSignature(prevOutScript, index, hashType)
|
||||||
var signature = privKey.sign(hash)
|
var signature = privKey.sign(hash)
|
||||||
var DERencoded = ecdsa.serializeSig(signature)
|
|
||||||
|
|
||||||
return Buffer.concat([
|
return signature.toScriptSignature(hashType)
|
||||||
new Buffer(DERencoded),
|
|
||||||
new Buffer([hashType])
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction.prototype.setInputScript = function(index, script) {
|
Transaction.prototype.setInputScript = function(index, script) {
|
||||||
|
@ -318,14 +313,11 @@ Transaction.prototype.setInputScript = function(index, script) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: could be validateInput(index, prevTxOut, pub)
|
// FIXME: could be validateInput(index, prevTxOut, pub)
|
||||||
Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, DERsig) {
|
Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, buffer) {
|
||||||
var type = DERsig.readUInt8(DERsig.length - 1)
|
var parsed = ECSignature.fromScriptSignature(buffer)
|
||||||
DERsig = DERsig.slice(0, -1)
|
var hash = this.hashForSignature(prevOutScript, index, parsed.hashType)
|
||||||
|
|
||||||
var hash = this.hashForSignature(prevOutScript, index, type)
|
return pubKey.verify(hash, parsed.signature)
|
||||||
var signature = ecdsa.parseSig(DERsig)
|
|
||||||
|
|
||||||
return pubKey.verify(hash, signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Transaction
|
module.exports = Transaction
|
||||||
|
|
109
test/ecdsa.js
109
test/ecdsa.js
|
@ -5,6 +5,7 @@ var message = require('../src/message')
|
||||||
var networks = require('../src/networks')
|
var networks = require('../src/networks')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
var ECSignature = require('../src/ecsignature')
|
||||||
|
|
||||||
var ecurve = require('ecurve')
|
var ecurve = require('ecurve')
|
||||||
var curve = ecurve.getCurveByName('secp256k1')
|
var curve = ecurve.getCurveByName('secp256k1')
|
||||||
|
@ -35,7 +36,7 @@ describe('ecdsa', function() {
|
||||||
}
|
}
|
||||||
var h1 = crypto.sha256(f.message)
|
var h1 = crypto.sha256(f.message)
|
||||||
var e = BigInteger.fromBuffer(h1)
|
var e = BigInteger.fromBuffer(h1)
|
||||||
var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.compact.i)
|
var Qprime = ecdsa.recoverPubKey(curve, e, signature, f.i)
|
||||||
|
|
||||||
assert(Qprime.equals(Q))
|
assert(Qprime.equals(Q))
|
||||||
})
|
})
|
||||||
|
@ -45,8 +46,8 @@ describe('ecdsa', function() {
|
||||||
var hash = message.magicHash('1111', networks.bitcoin)
|
var hash = message.magicHash('1111', networks.bitcoin)
|
||||||
var e = BigInteger.fromBuffer(hash)
|
var e = BigInteger.fromBuffer(hash)
|
||||||
|
|
||||||
var signature = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64')
|
var signatureBuffer = new Buffer('INcvXVVEFyIfHLbDX+xoxlKFn3Wzj9g0UbhObXdMq+YMKC252o5RHFr0/cKdQe1WsBLUBi4morhgZ77obDJVuV0=', 'base64')
|
||||||
var parsed = ecdsa.parseSigCompact(signature)
|
var signature = ECSignature.fromCompact(signatureBuffer).signature
|
||||||
var points = [
|
var points = [
|
||||||
'03e3a8c44a8bf712f1fbacee274fb19c0239b1a9e877eff0075ea335f2be8ff380',
|
'03e3a8c44a8bf712f1fbacee274fb19c0239b1a9e877eff0075ea335f2be8ff380',
|
||||||
'0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
'0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
||||||
|
@ -56,7 +57,7 @@ describe('ecdsa', function() {
|
||||||
|
|
||||||
points.forEach(function(expectedHex, i) {
|
points.forEach(function(expectedHex, i) {
|
||||||
it('recovers an expected point for i of ' + i, function() {
|
it('recovers an expected point for i of ' + i, function() {
|
||||||
var Qprime = ecdsa.recoverPubKey(curve, e, parsed.signature, i)
|
var Qprime = ecdsa.recoverPubKey(curve, e, signature, i)
|
||||||
var QprimeHex = Qprime.getEncoded().toString('hex')
|
var QprimeHex = Qprime.getEncoded().toString('hex')
|
||||||
|
|
||||||
assert.equal(QprimeHex, expectedHex)
|
assert.equal(QprimeHex, expectedHex)
|
||||||
|
@ -67,10 +68,7 @@ describe('ecdsa', function() {
|
||||||
fixtures.invalid.recoverPubKey.forEach(function(f) {
|
fixtures.invalid.recoverPubKey.forEach(function(f) {
|
||||||
it('throws on ' + f.description, function() {
|
it('throws on ' + f.description, function() {
|
||||||
var e = BigInteger.fromHex(f.e)
|
var e = BigInteger.fromHex(f.e)
|
||||||
var signature = {
|
var signature = new ECSignature(new BigInteger(f.signature.r), new BigInteger(f.signature.s))
|
||||||
r: new BigInteger(f.signature.r),
|
|
||||||
s: new BigInteger(f.signature.s)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
ecdsa.recoverPubKey(curve, e, signature, f.i)
|
ecdsa.recoverPubKey(curve, e, signature, f.i)
|
||||||
|
@ -105,13 +103,12 @@ describe('ecdsa', function() {
|
||||||
fixtures.valid.forEach(function(f) {
|
fixtures.valid.forEach(function(f) {
|
||||||
it('verifies a valid signature for \"' + f.message + '\"', function() {
|
it('verifies a valid signature for \"' + f.message + '\"', function() {
|
||||||
var d = BigInteger.fromHex(f.d)
|
var d = BigInteger.fromHex(f.d)
|
||||||
var Q = curve.params.G.multiply(d)
|
|
||||||
|
|
||||||
var signature = {
|
|
||||||
r: new BigInteger(f.signature.r),
|
|
||||||
s: new BigInteger(f.signature.s)
|
|
||||||
}
|
|
||||||
var e = BigInteger.fromBuffer(crypto.sha256(f.message))
|
var e = BigInteger.fromBuffer(crypto.sha256(f.message))
|
||||||
|
var signature = new ECSignature(
|
||||||
|
new BigInteger(f.signature.r),
|
||||||
|
new BigInteger(f.signature.s)
|
||||||
|
)
|
||||||
|
var Q = curve.params.G.multiply(d)
|
||||||
|
|
||||||
assert(ecdsa.verifyRaw(curve, e, signature, Q))
|
assert(ecdsa.verifyRaw(curve, e, signature, Q))
|
||||||
})
|
})
|
||||||
|
@ -121,90 +118,14 @@ describe('ecdsa', function() {
|
||||||
it('fails to verify with ' + f.description, function() {
|
it('fails to verify with ' + f.description, function() {
|
||||||
var d = BigInteger.fromHex(f.d)
|
var d = BigInteger.fromHex(f.d)
|
||||||
var e = BigInteger.fromHex(f.e)
|
var e = BigInteger.fromHex(f.e)
|
||||||
var signature = {
|
var signature = new ECSignature(
|
||||||
r: new BigInteger(f.signature.r),
|
new BigInteger(f.signature.r),
|
||||||
s: new BigInteger(f.signature.s)
|
new BigInteger(f.signature.s)
|
||||||
}
|
)
|
||||||
var Q = curve.params.G.multiply(d)
|
var Q = curve.params.G.multiply(d)
|
||||||
|
|
||||||
assert.equal(ecdsa.verifyRaw(curve, e, signature, Q), false)
|
assert.equal(ecdsa.verifyRaw(curve, e, signature, Q), false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('serializeSig', function() {
|
|
||||||
it('encodes a DER signature', function() {
|
|
||||||
fixtures.valid.forEach(function(f) {
|
|
||||||
var signature = {
|
|
||||||
r: new BigInteger(f.signature.r),
|
|
||||||
s: new BigInteger(f.signature.s)
|
|
||||||
}
|
|
||||||
|
|
||||||
var signature = new Buffer(ecdsa.serializeSig(signature))
|
|
||||||
assert.equal(signature.toString('hex'), f.DER)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('parseSig', function() {
|
|
||||||
it('decodes the correct signature', function() {
|
|
||||||
fixtures.valid.forEach(function(f) {
|
|
||||||
var buffer = new Buffer(f.DER, 'hex')
|
|
||||||
var signature = ecdsa.parseSig(buffer)
|
|
||||||
|
|
||||||
assert.equal(signature.r.toString(), f.signature.r)
|
|
||||||
assert.equal(signature.s.toString(), f.signature.s)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
fixtures.invalid.DER.forEach(function(f) {
|
|
||||||
it('throws on ' + f.hex, function() {
|
|
||||||
var buffer = new Buffer(f.hex, 'hex')
|
|
||||||
|
|
||||||
assert.throws(function() {
|
|
||||||
ecdsa.parseSig(buffer)
|
|
||||||
}, new RegExp(f.exception))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('serializeSigCompact', function() {
|
|
||||||
fixtures.valid.forEach(function(f) {
|
|
||||||
it('encodes ' + f.compact.hex + ' correctly', function() {
|
|
||||||
var signature = {
|
|
||||||
r: new BigInteger(f.signature.r),
|
|
||||||
s: new BigInteger(f.signature.s)
|
|
||||||
}
|
|
||||||
var i = f.compact.i
|
|
||||||
var compressed = f.compact.compressed
|
|
||||||
|
|
||||||
var signature = ecdsa.serializeSigCompact(signature, i, compressed)
|
|
||||||
assert.equal(signature.toString('hex'), f.compact.hex)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('parseSigCompact', function() {
|
|
||||||
fixtures.valid.forEach(function(f) {
|
|
||||||
it('decodes ' + f.compact.hex + ' correctly', function() {
|
|
||||||
var buffer = new Buffer(f.compact.hex, 'hex')
|
|
||||||
var parsed = ecdsa.parseSigCompact(buffer)
|
|
||||||
|
|
||||||
assert.equal(parsed.signature.r.toString(), f.signature.r)
|
|
||||||
assert.equal(parsed.signature.s.toString(), f.signature.s)
|
|
||||||
assert.equal(parsed.i, f.compact.i)
|
|
||||||
assert.equal(parsed.compressed, f.compact.compressed)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
fixtures.invalid.compact.forEach(function(f) {
|
|
||||||
it('throws on ' + f.hex, function() {
|
|
||||||
var buffer = new Buffer(f.hex, 'hex')
|
|
||||||
|
|
||||||
assert.throws(function() {
|
|
||||||
ecdsa.parseSigCompact(buffer)
|
|
||||||
}, new RegExp(f.exception))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
82
test/ecsignature.js
Normal file
82
test/ecsignature.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
var assert = require('assert')
|
||||||
|
|
||||||
|
var BigInteger = require('bigi')
|
||||||
|
var ECSignature = require('../src/ecsignature')
|
||||||
|
|
||||||
|
var fixtures = require('./fixtures/ecsignature.json')
|
||||||
|
|
||||||
|
describe('ECSignature', function() {
|
||||||
|
describe('toCompact', function() {
|
||||||
|
fixtures.valid.forEach(function(f) {
|
||||||
|
it('encodes ' + f.compact.hex + ' correctly', function() {
|
||||||
|
var signature = new ECSignature(
|
||||||
|
new BigInteger(f.signature.r),
|
||||||
|
new BigInteger(f.signature.s)
|
||||||
|
)
|
||||||
|
|
||||||
|
var buffer = signature.toCompact(f.compact.i, f.compact.compressed)
|
||||||
|
assert.equal(buffer.toString('hex'), f.compact.hex)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fromCompact', function() {
|
||||||
|
fixtures.valid.forEach(function(f) {
|
||||||
|
it('decodes ' + f.compact.hex + ' correctly', function() {
|
||||||
|
var buffer = new Buffer(f.compact.hex, 'hex')
|
||||||
|
var parsed = ECSignature.fromCompact(buffer)
|
||||||
|
|
||||||
|
assert.equal(parsed.compressed, f.compact.compressed)
|
||||||
|
assert.equal(parsed.i, f.compact.i)
|
||||||
|
assert.equal(parsed.signature.r.toString(), f.signature.r)
|
||||||
|
assert.equal(parsed.signature.s.toString(), f.signature.s)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
fixtures.invalid.compact.forEach(function(f) {
|
||||||
|
it('throws on ' + f.hex, function() {
|
||||||
|
var buffer = new Buffer(f.hex, 'hex')
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
ECSignature.fromCompact(buffer)
|
||||||
|
}, new RegExp(f.exception))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('toDER', function() {
|
||||||
|
it('encodes a DER signature', function() {
|
||||||
|
fixtures.valid.forEach(function(f) {
|
||||||
|
var signature = new ECSignature(
|
||||||
|
new BigInteger(f.signature.r),
|
||||||
|
new BigInteger(f.signature.s)
|
||||||
|
)
|
||||||
|
|
||||||
|
var DER = signature.toDER()
|
||||||
|
assert.equal(DER.toString('hex'), f.DER)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('fromDER', function() {
|
||||||
|
it('decodes the correct signature', function() {
|
||||||
|
fixtures.valid.forEach(function(f) {
|
||||||
|
var buffer = new Buffer(f.DER, 'hex')
|
||||||
|
var signature = ECSignature.fromDER(buffer)
|
||||||
|
|
||||||
|
assert.equal(signature.r.toString(), f.signature.r)
|
||||||
|
assert.equal(signature.s.toString(), f.signature.s)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
fixtures.invalid.DER.forEach(function(f) {
|
||||||
|
it('throws on ' + f.hex, function() {
|
||||||
|
var buffer = new Buffer(f.hex, 'hex')
|
||||||
|
|
||||||
|
assert.throws(function() {
|
||||||
|
ECSignature.fromDER(buffer)
|
||||||
|
}, new RegExp(f.exception))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
85
test/fixtures/ecdsa.json
vendored
85
test/fixtures/ecdsa.json
vendored
|
@ -4,12 +4,7 @@
|
||||||
"d": "01",
|
"d": "01",
|
||||||
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
|
"k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5",
|
||||||
"message": "Everything should be made as simple as possible, but not simpler.",
|
"message": "Everything should be made as simple as possible, but not simpler.",
|
||||||
"compact": {
|
"i": 0,
|
||||||
"hex": "1f33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262",
|
|
||||||
"compressed": true,
|
|
||||||
"i": 0
|
|
||||||
},
|
|
||||||
"DER": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
|
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
|
||||||
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
|
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
|
||||||
|
@ -19,12 +14,7 @@
|
||||||
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
||||||
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
|
"k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4",
|
||||||
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
|
"message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.",
|
||||||
"compact": {
|
"i": 0,
|
||||||
"hex": "1b54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5",
|
|
||||||
"compressed": false,
|
|
||||||
"i": 0
|
|
||||||
},
|
|
||||||
"DER": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
|
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
|
||||||
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
|
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
|
||||||
|
@ -34,12 +24,7 @@
|
||||||
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
"d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
||||||
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
|
"k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5",
|
||||||
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
|
"message": "Not only is the Universe stranger than we think, it is stranger than we can think.",
|
||||||
"compact": {
|
"i": 0,
|
||||||
"hex": "1fff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283",
|
|
||||||
"compressed": true,
|
|
||||||
"i": 0
|
|
||||||
},
|
|
||||||
"DER": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
|
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
|
||||||
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
|
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
|
||||||
|
@ -49,12 +34,7 @@
|
||||||
"d": "0000000000000000000000000000000000000000000000000000000000000001",
|
"d": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||||
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
|
"k": "f0cd2ba5fc7c183de589f6416220a36775a146740798756d8d949f7166dcc87f",
|
||||||
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
|
"message": "How wonderful that we have met with a paradox. Now we have some hope of making progress.",
|
||||||
"compact": {
|
"i": 1,
|
||||||
"hex": "1cc0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3",
|
|
||||||
"compressed": false,
|
|
||||||
"i": 1
|
|
||||||
},
|
|
||||||
"DER": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
|
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
|
||||||
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
|
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
|
||||||
|
@ -64,12 +44,7 @@
|
||||||
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
|
"d": "69ec59eaa1f4f2e36b639716b7c30ca86d9a5375c7b38d8918bd9c0ebc80ba64",
|
||||||
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
|
"k": "6bb4a594ad57c1aa22dbe991a9d8501daf4688bf50a4892ef21bd7c711afda97",
|
||||||
"message": "Computer science is no more about computers than astronomy is about telescopes.",
|
"message": "Computer science is no more about computers than astronomy is about telescopes.",
|
||||||
"compact": {
|
"i": 0,
|
||||||
"hex": "1f7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6",
|
|
||||||
"compressed": true,
|
|
||||||
"i": 0
|
|
||||||
},
|
|
||||||
"DER": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
|
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
|
||||||
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
|
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
|
||||||
|
@ -79,12 +54,7 @@
|
||||||
"d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637",
|
"d": "00000000000000000000000000007246174ab1e92e9149c6e446fe194d072637",
|
||||||
"k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb",
|
"k": "097b5c8ee22c3ea78a4d3635e0ff6fe85a1eb92ce317ded90b9e71aab2b861cb",
|
||||||
"message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough",
|
"message": "...if you aren't, at any given time, scandalized by code you wrote five or even three years ago, you're not learning anywhere near enough",
|
||||||
"compact": {
|
"i": 1,
|
||||||
"hex": "1cfbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37",
|
|
||||||
"compressed": false,
|
|
||||||
"i": 1
|
|
||||||
},
|
|
||||||
"DER": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
|
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
|
||||||
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
|
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
|
||||||
|
@ -94,12 +64,7 @@
|
||||||
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
|
"d": "000000000000000000000000000000000000000000056916d0f9b31dc9b637f3",
|
||||||
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
|
"k": "19355c36c8cbcdfb2382e23b194b79f8c97bf650040fc7728dfbf6b39a97c25b",
|
||||||
"message": "The question of whether computers can think is like the question of whether submarines can swim.",
|
"message": "The question of whether computers can think is like the question of whether submarines can swim.",
|
||||||
"compact": {
|
"i": 1,
|
||||||
"hex": "20cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef",
|
|
||||||
"compressed": true,
|
|
||||||
"i": 1
|
|
||||||
},
|
|
||||||
"DER": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef",
|
|
||||||
"signature": {
|
"signature": {
|
||||||
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
|
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
|
||||||
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
|
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
|
||||||
|
@ -107,42 +72,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"invalid": {
|
"invalid": {
|
||||||
"compact": [
|
|
||||||
{
|
|
||||||
"exception": "Invalid signature parameter",
|
|
||||||
"hex": "23987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Invalid signature length",
|
|
||||||
"hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62000000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Invalid signature length",
|
|
||||||
"hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e9379"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"DER": [
|
|
||||||
{
|
|
||||||
"exception": "Invalid sequence length",
|
|
||||||
"hex": "30ff0204ffffffff0204ffffffff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Invalid sequence length",
|
|
||||||
"hex": "300c0304ffffffff0304ffffffff0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Expected a DER integer",
|
|
||||||
"hex": "300cff04ffffffff0204ffffffff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Expected a DER integer \\(2\\)",
|
|
||||||
"hex": "300c0202ffffffff0204ffffffff"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"exception": "Invalid DER encoding",
|
|
||||||
"hex": "300c0204ffffffff0202ffffffff"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"recoverPubKey": [
|
"recoverPubKey": [
|
||||||
{
|
{
|
||||||
"description": "Invalid r value (== 0)",
|
"description": "Invalid r value (== 0)",
|
||||||
|
|
126
test/fixtures/ecsignature.json
vendored
Normal file
126
test/fixtures/ecsignature.json
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{
|
||||||
|
"valid": [
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1f33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262",
|
||||||
|
"compressed": true,
|
||||||
|
"i": 0
|
||||||
|
},
|
||||||
|
"DER": "3044022033a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c902206f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262",
|
||||||
|
"signature": {
|
||||||
|
"r": "23362334225185207751494092901091441011938859014081160902781146257181456271561",
|
||||||
|
"s": "50433721247292933944369538617440297985091596895097604618403996029256432099938"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1b54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5",
|
||||||
|
"compressed": false,
|
||||||
|
"i": 0
|
||||||
|
},
|
||||||
|
"DER": "3044022054c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed022007082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5",
|
||||||
|
"signature": {
|
||||||
|
"r": "38341707918488238920692284707283974715538935465589664377561695343399725051885",
|
||||||
|
"s": "3180566392414476763164587487324397066658063772201694230600609996154610926757"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1fff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283",
|
||||||
|
"compressed": true,
|
||||||
|
"i": 0
|
||||||
|
},
|
||||||
|
"DER": "3045022100ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd002206fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283",
|
||||||
|
"signature": {
|
||||||
|
"r": "115464191557905790016094131873849783294273568009648050793030031933291767741904",
|
||||||
|
"s": "50562520307781850052192542766631199590053690478900449960232079510155113443971"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1cc0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3",
|
||||||
|
"compressed": false,
|
||||||
|
"i": 1
|
||||||
|
},
|
||||||
|
"DER": "3045022100c0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d3022075afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3",
|
||||||
|
"signature": {
|
||||||
|
"r": "87230998027579607140680851455601772643840468630989315269459846730712163783123",
|
||||||
|
"s": "53231320085894623106179381504478252331065330583563809963303318469380290929875"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1f7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6",
|
||||||
|
"compressed": true,
|
||||||
|
"i": 0
|
||||||
|
},
|
||||||
|
"DER": "304402207186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d02200de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6",
|
||||||
|
"signature": {
|
||||||
|
"r": "51348483531757779992459563033975330355971795607481991320287437101831125115997",
|
||||||
|
"s": "6277080015686056199074771961940657638578000617958603212944619747099038735862"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "1cfbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37",
|
||||||
|
"compressed": false,
|
||||||
|
"i": 1
|
||||||
|
},
|
||||||
|
"DER": "3045022100fbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda48702200e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37",
|
||||||
|
"signature": {
|
||||||
|
"r": "113979859486826658566290715281614250298918272782414232881639314569529560769671",
|
||||||
|
"s": "6517071009538626957379450615706485096874328019806177698938278220732027419959"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compact": {
|
||||||
|
"hex": "20cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef",
|
||||||
|
"compressed": true,
|
||||||
|
"i": 1
|
||||||
|
},
|
||||||
|
"DER": "3045022100cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf9022006ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef",
|
||||||
|
"signature": {
|
||||||
|
"r": "93122007060065279508564838030979550535085999589142852106617159184757394422777",
|
||||||
|
"s": "3078539468410661027472930027406594684630312677495124015420811882501887769839"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"invalid": {
|
||||||
|
"compact": [
|
||||||
|
{
|
||||||
|
"exception": "Invalid signature parameter",
|
||||||
|
"hex": "23987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Invalid signature length",
|
||||||
|
"hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62000000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Invalid signature length",
|
||||||
|
"hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e9379"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"DER": [
|
||||||
|
{
|
||||||
|
"exception": "Invalid sequence length",
|
||||||
|
"hex": "30ff0204ffffffff0204ffffffff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Invalid sequence length",
|
||||||
|
"hex": "300c0304ffffffff0304ffffffff0000"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Expected a DER integer",
|
||||||
|
"hex": "300cff04ffffffff0204ffffffff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Expected a DER integer \\(2\\)",
|
||||||
|
"hex": "300c0202ffffffff0204ffffffff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"exception": "Invalid DER encoding",
|
||||||
|
"hex": "300c0204ffffffff0202ffffffff"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue