package org.ripple.power.txns.btc;
import org.ripple.bouncycastle.asn1.ASN1InputStream;
import org.ripple.bouncycastle.asn1.ASN1Integer;
import org.ripple.bouncycastle.asn1.DERSequenceGenerator;
import org.ripple.bouncycastle.asn1.DLSequence;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
/**
* ECDSASignature is an elliptic curve digital signature consisting of the
* R and S values.
*/
public class ECDSASignature {
/** R and S components of the digital signature */
private BigInteger r;
private BigInteger s;
/**
* Creates a digital signature from the R and S values
*
* @param r R value
* @param s S value
*/
public ECDSASignature(BigInteger r, BigInteger s) {
this.r = r;
this.s = s;
}
/**
* Creates a digital signature from the DER-encoded values
*
* @param encodedStream DER-encoded value
* @throws ECException Unable to decode the stream
*/
public ECDSASignature(byte[] encodedStream) throws ECException {
try {
try (ASN1InputStream decoder = new ASN1InputStream(encodedStream)) {
DLSequence seq = (DLSequence)decoder.readObject();
r = ((ASN1Integer)seq.getObjectAt(0)).getPositiveValue();
s = ((ASN1Integer)seq.getObjectAt(1)).getPositiveValue();
}
} catch (ClassCastException | IOException exc) {
throw new ECException("Unable to decode signature", exc);
}
}
/**
* Returns the R value
*
* @return R component
*/
public BigInteger getR() {
return r;
}
/**
* Returns the S value
*
* @return S component
*/
public BigInteger getS() {
return s;
}
/**
* Encodes R and S as a DER-encoded byte stream
*
* @return DER-encoded byte stream
*/
public byte[] encodeToDER() {
byte[] encodedBytes = null;
try {
try (ByteArrayOutputStream outStream = new ByteArrayOutputStream(80)) {
DERSequenceGenerator seq = new DERSequenceGenerator(outStream);
seq.addObject(new ASN1Integer(r));
seq.addObject(new ASN1Integer(s));
seq.close();
encodedBytes = outStream.toByteArray();
}
} catch (IOException exc) {
throw new IllegalStateException("Unexpected IOException", exc);
}
return encodedBytes;
}
}