Search code examples
javabouncycastlesignatureecdsa

ECDSA DER signature


I have generated an ECDSA signature in Java and I would like to get the R and S values from it in order to have the COSE encoded signature. It is my understanding that the signature I have generated is DER encoded (by default using bouncyCastle). I properly retrieve the R and S values when I used P-256 curve (SHA256withECDSA).

I have some issues parsing the signature from one encoding to another when I use other curves (P-521, P-384).

Here after is how I parse it :

public static byte[] extractRandSToCose(byte[] signature) {

    if (signature[0] == 0x30) {
        //parse R
        int rSize = signature[3];
        BigInteger rBigInt = new BigInteger(Arrays.copyOfRange(signature, 4, rSize+4));
        //strip out sign byte 0x00
        byte[] r = toByteArrayUnsigned(rBigInt);

        //parse S
        int sSize = signature[5 + rSize];
        int index = rSize + 6;
        BigInteger sBigInt = new BigInteger(Arrays.copyOfRange(signature, index, index+sSize));
        //strip out sign byte 0x00
        byte[] s = toByteArrayUnsigned(sBigInt);

        return Bytes.concat(r,s);
    }
    return null;
}


public static byte[] toByteArrayUnsigned(BigInteger bigInteger) {
    byte[] extractedBytes = bigInteger.toByteArray();
    int skipped = 0;
    boolean skip = true;
    for (byte b : extractedBytes) {
        boolean signByte = b == 0x00;

        if (skip && signByte) {
            skipped++;
            continue;
        } else if (skip){
            skip = false;
        }
    }
    extractedBytes = Arrays.copyOfRange(extractedBytes, skipped, extractedBytes.length);
    return extractedBytes;
}

I dont get what I am doing wrong.

PS: Those methods works from time to time. It works everytime for P-256 (whether the DER signature is 70 71 or 72 bytes long and properly gives me a 64 byte long Cose signature), P-384 (same for 102, 103 104 byte long and properly gives me a 96 byte long cose signature) but only works half the time for P-521 (138, 139, 140 byte long and even when it does the cose signature is only 31 byte long....)


Solution

  • {hash}withECDSAinP1363Format did the trick ! Thank you ! I didn't even needed to read all those specs to see how to parse it...