/** * Sign a hash with the private key of this key pair. * @param transactionHash the hash to sign * @return An {@link ECDSASignature} of the hash */ public ECDSASignature sign(byte[] transactionHash) { ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, Sign.CURVE); signer.init(true, privKey); BigInteger[] components = signer.generateSignature(transactionHash); return new ECDSASignature(components[0], components[1]).toCanonicalised(); }
/** * Will automatically adjust the S component to be less than or equal to half the curve * order, if necessary. This is required because for every signature (r,s) the signature * (r, -s (mod N)) is a valid signature of the same message. However, we dislike the * ability to modify the bits of a Bitcoin transaction after it's been signed, as that * violates various assumed invariants. Thus in future only one of those forms will be * considered legal and the other will be banned. * * @return the signature in a canonicalised form. */ public ECDSASignature toCanonicalised() { if (!isCanonical()) { // The order of the curve is the number of valid points that exist on that curve. // If S is in the upper half of the number of valid points, then bring it back to // the lower half. Otherwise, imagine that // N = 10 // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. // 10 - 8 == 2, giving us always the latter solution, which is canonical. return new ECDSASignature(r, Sign.CURVE.getN().subtract(s)); } else { return this; } } }
static BigInteger signedMessageHashToKey( byte[] messageHash, SignatureData signatureData) throws SignatureException { byte[] r = signatureData.getR(); byte[] s = signatureData.getS(); verifyPrecondition(r != null && r.length == 32, "r must be 32 bytes"); verifyPrecondition(s != null && s.length == 32, "s must be 32 bytes"); int header = signatureData.getV() & 0xFF; // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, // 0x1D = second key with even y, 0x1E = second key with odd y if (header < 27 || header > 34) { throw new SignatureException("Header byte out of range: " + header); } ECDSASignature sig = new ECDSASignature( new BigInteger(1, signatureData.getR()), new BigInteger(1, signatureData.getS())); int recId = header - 27; BigInteger key = recoverFromSignature(recId, sig, messageHash); if (key == null) { throw new SignatureException("Could not recover public key from signature"); } return key; }
BigInteger publicKey = Sign.recoverFromSignature( (byte) i, new ECDSASignature(new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())), msgHash);
/** * Sign a hash with the private key of this key pair. * @param transactionHash the hash to sign * @return An {@link ECDSASignature} of the hash */ public ECDSASignature sign(byte[] transactionHash) { ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())); ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey, Sign.CURVE); signer.init(true, privKey); BigInteger[] components = signer.generateSignature(transactionHash); return new ECDSASignature(components[0], components[1]).toCanonicalised(); }
/** * Will automatically adjust the S component to be less than or equal to half the curve * order, if necessary. This is required because for every signature (r,s) the signature * (r, -s (mod N)) is a valid signature of the same message. However, we dislike the * ability to modify the bits of a Bitcoin transaction after it's been signed, as that * violates various assumed invariants. Thus in future only one of those forms will be * considered legal and the other will be banned. * * @return the signature in a canonicalised form. */ public ECDSASignature toCanonicalised() { if (!isCanonical()) { // The order of the curve is the number of valid points that exist on that curve. // If S is in the upper half of the number of valid points, then bring it back to // the lower half. Otherwise, imagine that // N = 10 // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions. // 10 - 8 == 2, giving us always the latter solution, which is canonical. return new ECDSASignature(r, Sign.CURVE.getN().subtract(s)); } else { return this; } } }
static BigInteger signedMessageHashToKey( byte[] messageHash, SignatureData signatureData) throws SignatureException { byte[] r = signatureData.getR(); byte[] s = signatureData.getS(); verifyPrecondition(r != null && r.length == 32, "r must be 32 bytes"); verifyPrecondition(s != null && s.length == 32, "s must be 32 bytes"); int header = signatureData.getV() & 0xFF; // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y, // 0x1D = second key with even y, 0x1E = second key with odd y if (header < 27 || header > 34) { throw new SignatureException("Header byte out of range: " + header); } ECDSASignature sig = new ECDSASignature( new BigInteger(1, signatureData.getR()), new BigInteger(1, signatureData.getS())); int recId = header - 27; BigInteger key = recoverFromSignature(recId, sig, messageHash); if (key == null) { throw new SignatureException("Could not recover public key from signature"); } return key; }