mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-13 10:45:51 +00:00
Improvements in ECKey.extractKeyFromASN1
- Check there's no extra data following the key - Confirm the ASN.1 tag number is correct on the publicKey field - Explicitly check the encoding is one we support - Rework the sanity check to avoid redundant parsing/multiplies
This commit is contained in:
parent
2b8fa07ae8
commit
a2e0908436
@ -784,22 +784,31 @@ public class ECKey implements EncryptableItem, Serializable {
|
|||||||
try {
|
try {
|
||||||
ASN1InputStream decoder = new ASN1InputStream(asn1privkey);
|
ASN1InputStream decoder = new ASN1InputStream(asn1privkey);
|
||||||
DLSequence seq = (DLSequence) decoder.readObject();
|
DLSequence seq = (DLSequence) decoder.readObject();
|
||||||
|
checkArgument(decoder.readObject() == null, "Input contains extra bytes");
|
||||||
|
decoder.close();
|
||||||
|
|
||||||
checkArgument(seq.size() == 4, "Input does not appear to be an ASN.1 OpenSSL EC private key");
|
checkArgument(seq.size() == 4, "Input does not appear to be an ASN.1 OpenSSL EC private key");
|
||||||
|
|
||||||
checkArgument(((ASN1Integer) seq.getObjectAt(0)).getValue().equals(BigInteger.ONE),
|
checkArgument(((ASN1Integer) seq.getObjectAt(0)).getValue().equals(BigInteger.ONE),
|
||||||
"Input is of wrong version");
|
"Input is of wrong version");
|
||||||
Object obj = seq.getObjectAt(1);
|
|
||||||
byte[] privbits = ((ASN1OctetString) obj).getOctets();
|
byte[] privbits = ((ASN1OctetString) seq.getObjectAt(1)).getOctets();
|
||||||
decoder.close();
|
|
||||||
BigInteger privkey = new BigInteger(1, privbits);
|
BigInteger privkey = new BigInteger(1, privbits);
|
||||||
byte[] pubbits = ((DERBitString)((ASN1TaggedObject)seq.getObjectAt(3)).getObject()).getBytes();
|
|
||||||
|
ASN1TaggedObject pubkey = (ASN1TaggedObject) seq.getObjectAt(3);
|
||||||
|
checkArgument(pubkey.getTagNo() == 1, "Input has 'publicKey' with bad tag number");
|
||||||
|
byte[] pubbits = ((DERBitString)pubkey.getObject()).getBytes();
|
||||||
|
checkArgument(pubbits.length == 33 || pubbits.length == 65, "Input has 'publicKey' with invalid length");
|
||||||
|
int encoding = pubbits[0] & 0xFF;
|
||||||
|
// Only allow compressed(2,3) and uncompressed(4), not infinity(0) or hybrid(6,7)
|
||||||
|
checkArgument(encoding >= 2 && encoding <= 4, "Input has 'publicKey' with invalid encoding");
|
||||||
|
|
||||||
// Now sanity check to ensure the pubkey bytes match the privkey.
|
// Now sanity check to ensure the pubkey bytes match the privkey.
|
||||||
byte[] compressed = publicKeyFromPrivate(privkey, true);
|
boolean compressed = (pubbits.length == 33);
|
||||||
if (Arrays.equals(pubbits, compressed))
|
ECKey key = new ECKey(privkey, null, compressed);
|
||||||
return new ECKey(privkey, compressed);
|
if (!Arrays.equals(key.getPubKey(), pubbits))
|
||||||
byte[] uncompressed = publicKeyFromPrivate(privkey, false);
|
|
||||||
if (Arrays.equals(pubbits, uncompressed))
|
|
||||||
return new ECKey(privkey, uncompressed);
|
|
||||||
throw new IllegalArgumentException("Public key in ASN.1 structure does not match private key.");
|
throw new IllegalArgumentException("Public key in ASN.1 structure does not match private key.");
|
||||||
|
return key;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e); // Cannot happen, reading from memory stream.
|
throw new RuntimeException(e); // Cannot happen, reading from memory stream.
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user