Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 67eafc6

Browse files
Jonathan PatchellJonathan Patchell
authored andcommitted
[FAB-6603] Java SDK Signatures with Standard JCA/JCE
Improvement [FAB-6603] changing CryptoPrimitives to use the standard JCA/JCE Signature class to perform the ECDSA signatures. The signature is then decoded in order to call preventMalleability. Change-Id: Ia69dade5008b5a1c91b3cd2186fc0c81fb9f3a39 Signed-off-by: Jonathan Patchell <Jonathan.Patchell@gemalto.com>
1 parent d963896 commit 67eafc6

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

src/main/java/org/hyperledger/fabric/sdk/security/CryptoPrimitives.java

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,17 @@
6161
import org.apache.commons.io.FileUtils;
6262
import org.apache.commons.logging.Log;
6363
import org.apache.commons.logging.LogFactory;
64+
import org.bouncycastle.asn1.ASN1Encodable;
65+
import org.bouncycastle.asn1.ASN1InputStream;
6466
import org.bouncycastle.asn1.ASN1Integer;
67+
import org.bouncycastle.asn1.ASN1Primitive;
68+
import org.bouncycastle.asn1.ASN1Sequence;
6569
import org.bouncycastle.asn1.DERSequenceGenerator;
6670
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
6771
import org.bouncycastle.asn1.x9.X9ECParameters;
6872
import org.bouncycastle.crypto.Digest;
6973
import org.bouncycastle.crypto.digests.SHA256Digest;
7074
import org.bouncycastle.crypto.digests.SHA3Digest;
71-
import org.bouncycastle.crypto.params.ECDomainParameters;
72-
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
73-
import org.bouncycastle.crypto.signers.ECDSASigner;
7475
import org.bouncycastle.jce.provider.BouncyCastleProvider;
7576
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
7677
import org.bouncycastle.operator.ContentSigner;
@@ -599,6 +600,42 @@ private KeyPair generateKey(String encryptionName, String curveName) throws Cryp
599600
}
600601
}
601602

603+
/**
604+
* Decodes an ECDSA signature and returns a two element BigInteger array.
605+
*
606+
* @param signature ECDSA signature bytes.
607+
* @return BigInteger array for the signature's r and s values
608+
* @throws Exception
609+
*/
610+
private static BigInteger[] decodeECDSASignature(byte[] signature) throws Exception {
611+
ByteArrayInputStream inStream = new ByteArrayInputStream(signature);
612+
ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
613+
ASN1Primitive asn1 = asnInputStream.readObject();
614+
615+
BigInteger[] sigs = new BigInteger[2];
616+
int count = 0;
617+
if (asn1 instanceof ASN1Sequence) {
618+
ASN1Sequence asn1Sequence = (ASN1Sequence) asn1;
619+
ASN1Encodable[] asn1Encodables = asn1Sequence.toArray();
620+
for (ASN1Encodable asn1Encodable : asn1Encodables) {
621+
ASN1Primitive asn1Primitive = asn1Encodable.toASN1Primitive();
622+
if (asn1Primitive instanceof ASN1Integer) {
623+
ASN1Integer asn1Integer = (ASN1Integer) asn1Primitive;
624+
BigInteger integer = asn1Integer.getValue();
625+
if (count < 2) {
626+
sigs[count] = integer;
627+
}
628+
count++;
629+
}
630+
}
631+
}
632+
if (count != 2) {
633+
throw new CryptoException(format("Invalid ECDSA signature. Expected count of 2 but got: %d. Signature is: %s", count,
634+
DatatypeConverter.printHexBinary(signature)));
635+
}
636+
return sigs;
637+
}
638+
602639

603640
/**
604641
* Sign data with the specified elliptic curve private key.
@@ -610,19 +647,16 @@ private KeyPair generateKey(String encryptionName, String curveName) throws Cryp
610647
*/
611648
private byte[] ecdsaSignToBytes(ECPrivateKey privateKey, byte[] data) throws CryptoException {
612649
try {
613-
final byte[] encoded = hash(data);
614-
615650
X9ECParameters params = ECNamedCurveTable.getByName(curveName);
616651
BigInteger curveN = params.getN();
617652

618-
ECDomainParameters ecParams = new ECDomainParameters(params.getCurve(), params.getG(), curveN,
619-
params.getH());
620-
621-
ECDSASigner signer = new ECDSASigner();
653+
Signature sig = SECURITY_PROVIDER == null ? Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM) :
654+
Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM, SECURITY_PROVIDER);
655+
sig.initSign(privateKey);
656+
sig.update(data);
657+
byte[] signature = sig.sign();
622658

623-
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKey.getS(), ecParams);
624-
signer.init(true, privKey);
625-
BigInteger[] sigs = signer.generateSignature(encoded);
659+
BigInteger[] sigs = decodeECDSASignature(signature);
626660

627661
sigs = preventMalleability(sigs, curveN);
628662

0 commit comments

Comments
 (0)