COSE.SignCommon.java Source code

Java tutorial

Introduction

Here is the source code for COSE.SignCommon.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package COSE;

import com.upokecenter.cbor.CBORObject;
import static java.lang.Integer.min;
import java.math.BigInteger;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA384Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.bouncycastle.math.ec.ECPoint;

/**
 *
 * @author jimsch
 */
public abstract class SignCommon extends Message {
    protected String contextString;

    byte[] computeSignature(byte[] rgbToBeSigned, CipherParameters key) throws CoseException {
        AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
        Digest digest;
        CBORObject cn;
        switch (alg) {
        case ECDSA_256:
            digest = new SHA256Digest();
            break;

        case ECDSA_384:
            digest = new SHA384Digest();
            break;

        case ECDSA_512:
            digest = new SHA512Digest();
            break;

        default:
            throw new CoseException("Unsupported Algorithm Specified");
        }

        switch (alg) {
        case ECDSA_256:
        case ECDSA_384:
        case ECDSA_512: {
            digest.update(rgbToBeSigned, 0, rgbToBeSigned.length);
            byte[] rgbDigest = new byte[digest.getDigestSize()];
            digest.doFinal(rgbDigest, 0);

            ECDSASigner ecdsa = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
            ecdsa.init(true, key);
            BigInteger[] sig = ecdsa.generateSignature(rgbDigest);

            int cb = (((ECPrivateKeyParameters) key).getParameters().getCurve().getFieldSize() + 7) / 8;
            byte[] r = sig[0].toByteArray();
            byte[] s = sig[1].toByteArray();

            byte[] sigs = new byte[cb * 2];
            int cbR = min(cb, r.length);
            System.arraycopy(r, r.length - cbR, sigs, cb - cbR, cbR);
            cbR = min(cb, s.length);
            System.arraycopy(s, s.length - cbR, sigs, cb + cb - cbR, cbR);

            return sigs;

        }

        default:
            throw new CoseException("Inernal error");
        }
    }

    byte[] computeSignature(byte[] rgbToBeSigned, OneKey cnKey) throws CoseException {
        AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
        Digest digest;
        CBORObject cn;

        switch (alg) {
        case ECDSA_256:
            digest = new SHA256Digest();
            break;

        case ECDSA_384:
            digest = new SHA384Digest();
            break;

        case ECDSA_512:
            digest = new SHA512Digest();
            break;

        default:
            throw new CoseException("Unsupported Algorithm Specified");
        }

        switch (alg) {
        case ECDSA_256:
        case ECDSA_384:
        case ECDSA_512: {
            digest.update(rgbToBeSigned, 0, rgbToBeSigned.length);
            byte[] rgbDigest = new byte[digest.getDigestSize()];
            digest.doFinal(rgbDigest, 0);

            cn = cnKey.get(KeyKeys.KeyType);
            if ((cn == null) || (cn != KeyKeys.KeyType_EC2))
                throw new CoseException("Must use key with key type EC2");
            cn = cnKey.get(KeyKeys.EC2_D);
            if (cn == null)
                throw new CoseException("Private key required to sign");

            X9ECParameters p = cnKey.GetCurve();
            ECDomainParameters parameters = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
            ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1, cn.GetByteString()),
                    parameters);

            ECDSASigner ecdsa = new ECDSASigner();
            ecdsa.init(true, privKey);
            BigInteger[] sig = ecdsa.generateSignature(rgbDigest);

            int cb = (p.getCurve().getFieldSize() + 7) / 8;
            byte[] r = sig[0].toByteArray();
            byte[] s = sig[1].toByteArray();

            byte[] sigs = new byte[cb * 2];
            int cbR = min(cb, r.length);
            System.arraycopy(r, r.length - cbR, sigs, cb - cbR, cbR);
            cbR = min(cb, s.length);
            System.arraycopy(s, s.length - cbR, sigs, cb + cb - cbR, cbR);

            return sigs;

        }

        default:
            throw new CoseException("Inernal error");
        }
    }

    boolean validateSignature(byte[] rgbToBeSigned, byte[] rgbSignature, CipherParameters key)
            throws CoseException {
        AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
        Digest digest;

        switch (alg) {
        case ECDSA_256:
            digest = new SHA256Digest();
            break;

        case ECDSA_384:
            digest = new SHA384Digest();
            break;

        case ECDSA_512:
            digest = new SHA512Digest();
            break;

        default:
            throw new CoseException("Unsupported algorithm specified");
        }

        switch (alg) {
        case ECDSA_256:
        case ECDSA_384:
        case ECDSA_512: {
            byte[] rgbR = new byte[rgbSignature.length / 2];
            byte[] rgbS = new byte[rgbSignature.length / 2];
            System.arraycopy(rgbSignature, 0, rgbR, 0, rgbR.length);
            System.arraycopy(rgbSignature, rgbR.length, rgbS, 0, rgbR.length);

            digest.update(rgbToBeSigned, 0, rgbToBeSigned.length);
            byte[] rgbDigest = new byte[digest.getDigestSize()];
            digest.doFinal(rgbDigest, 0);

            ECDSASigner ecdsa = new ECDSASigner();
            ecdsa.init(false, key);
            return ecdsa.verifySignature(rgbDigest, new BigInteger(1, rgbR), new BigInteger(1, rgbS));
        }

        default:
            throw new CoseException("Internal error");
        }
    }

    boolean validateSignature(byte[] rgbToBeSigned, byte[] rgbSignature, OneKey cnKey) throws CoseException {
        AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
        Digest digest;

        switch (alg) {
        case ECDSA_256:
            digest = new SHA256Digest();
            break;

        case ECDSA_384:
            digest = new SHA384Digest();
            break;

        case ECDSA_512:
            digest = new SHA512Digest();
            break;

        default:
            throw new CoseException("Unsupported algorithm specified");
        }

        switch (alg) {
        case ECDSA_256:
        case ECDSA_384:
        case ECDSA_512: {
            byte[] rgbR = new byte[rgbSignature.length / 2];
            byte[] rgbS = new byte[rgbSignature.length / 2];
            System.arraycopy(rgbSignature, 0, rgbR, 0, rgbR.length);
            System.arraycopy(rgbSignature, rgbR.length, rgbS, 0, rgbR.length);

            digest.update(rgbToBeSigned, 0, rgbToBeSigned.length);
            byte[] rgbDigest = new byte[digest.getDigestSize()];
            digest.doFinal(rgbDigest, 0);

            X9ECParameters p = cnKey.GetCurve();
            ECDomainParameters parameters = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH());
            BigInteger bnX = new BigInteger(1, cnKey.get(KeyKeys.EC2_X).GetByteString());
            ECPoint point = p.getCurve().createPoint(bnX,
                    new BigInteger(1, cnKey.get(KeyKeys.EC2_Y).GetByteString()));

            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(point, parameters);

            ECDSASigner ecdsa = new ECDSASigner();
            ecdsa.init(false, pubKey);
            return ecdsa.verifySignature(rgbDigest, new BigInteger(1, rgbR), new BigInteger(1, rgbS));
        }

        default:
            throw new CoseException("Internal error");
        }
    }

    /**
     * 
     * @deprecated As of COSE 0.9.1, replaced by {@link #OneKey.GetCurve()}.
     * @param cnKey key to get the curve for
     * @return BouncyCastle object describing the curve.
     * @throws CoseException Errors generated by the COSE module
     */

    @Deprecated
    static X9ECParameters GetCurve(CBORObject cnKey) throws CoseException {
        if (cnKey.get(KeyKeys.KeyType.AsCBOR()) != KeyKeys.KeyType_EC2)
            throw new CoseException("Not an EC2 key");
        CBORObject cnCurve = cnKey.get(KeyKeys.EC2_Curve.AsCBOR());

        if (cnCurve == KeyKeys.EC2_P256)
            return NISTNamedCurves.getByName("P-256");
        if (cnCurve == KeyKeys.EC2_P384)
            return NISTNamedCurves.getByName("P-384");
        if (cnCurve == KeyKeys.EC2_P521)
            return NISTNamedCurves.getByName("P-521");
        throw new CoseException("Unsupported curve " + cnCurve);
    }
}