handle low S values in signatures.
This commit is contained in:
parent
de455fa3e9
commit
a71da261ad
@ -31,5 +31,6 @@ bcoin.protocol.network.set(process.env.BCOIN_NETWORK || 'main');
|
||||
|
||||
bcoin.bn = bn;
|
||||
bcoin.elliptic = elliptic;
|
||||
bcoin.signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
bcoin.hash = hash;
|
||||
bcoin.async = async;
|
||||
|
||||
@ -237,9 +237,12 @@ script.subscript = function subscript(s, lastSep) {
|
||||
return res;
|
||||
};
|
||||
|
||||
script.checksig = function checksig(hash, sig, pub) {
|
||||
script.checksig = function checksig(msg, sig, pub) {
|
||||
var k;
|
||||
|
||||
if (pub.getPublic)
|
||||
pub = pub.getPublic();
|
||||
|
||||
try {
|
||||
k = bcoin.ecdsa.keyPair({ pub: pub });
|
||||
} catch (e) {
|
||||
@ -255,7 +258,7 @@ script.checksig = function checksig(hash, sig, pub) {
|
||||
// Use a try catch in case there are
|
||||
// any uncaught errors for bad inputs in verify().
|
||||
try {
|
||||
return bcoin.ecdsa.verify(hash, sig, pub);
|
||||
return bcoin.ecdsa.verify(msg, sig, pub);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
@ -1542,6 +1545,54 @@ script.isValidSignature = function isValidSignature(sig, allowZero) {
|
||||
return true;
|
||||
};
|
||||
|
||||
script.isLowDER = function isLowDER(sig, type) {
|
||||
var half = bcoin.ecdsa.n.ushrn(1);
|
||||
|
||||
if (!sig.s) {
|
||||
assert(utils.isBuffer(sig));
|
||||
|
||||
if (sig[sig.length - 1] === type)
|
||||
sig = sig.slice(0, -1);
|
||||
|
||||
try {
|
||||
sig = new bcoin.signature(sig);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Technically a negative S value is low,
|
||||
// but we don't want to ever use negative
|
||||
// S values in bitcoin.
|
||||
if (sig.s.cmpn(0) <= 0)
|
||||
return false;
|
||||
|
||||
// If S is greater than half the order,
|
||||
// it's too high.
|
||||
if (sig.s.cmp(half) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
script.sign = function sign(msg, key) {
|
||||
var half = bcoin.ecdsa.n.ushrn(1);
|
||||
var sig = bcoin.ecdsa.sign(msg, key.priv);
|
||||
|
||||
// Elliptic shouldn't be generating
|
||||
// negative S values.
|
||||
assert(sig.s.cmpn(0) > 0);
|
||||
|
||||
// S value is already low.
|
||||
if (sig.s.cmp(half) <= 0)
|
||||
return sig.toDER();
|
||||
|
||||
// Subtract from the `n` order to make it smaller.
|
||||
sig.s = bcoin.ecdsa.n.sub(sig.s);
|
||||
|
||||
return sig.toDER();
|
||||
};
|
||||
|
||||
script.format = function format(input, output) {
|
||||
var scripts = [];
|
||||
var prev, redeem;
|
||||
|
||||
@ -251,7 +251,10 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
||||
hash = this.signatureHash(index, redeem, type);
|
||||
|
||||
// Sign the transaction with our one input
|
||||
signature = bcoin.ecdsa.sign(hash, key.priv).toDER();
|
||||
signature = bcoin.script.sign(hash, key);
|
||||
|
||||
// Something is broken if this doesn't work:
|
||||
assert(bcoin.script.checksig(hash, signature, key));
|
||||
|
||||
// Add the sighash as a single byte to the signature
|
||||
signature = signature.concat(type);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user