All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.crypto.asymmetric.KeyUtils Maven / Gradle / Ivy

Go to download

The FIPS 140-3 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-3 level 1. This jar contains JCE provider and low-level API for the BC-FJA version 2.0.0, FIPS Certificate #4743. Please see certificate for certified platform details.

There is a newer version: 2.0.0
Show newest version
package org.bouncycastle.crypto.asymmetric;

import java.math.BigInteger;
import java.security.Permission;
import java.security.SecureRandom;

import javax.security.auth.Destroyable;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.fips.FipsDRBG;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.internal.Primes;
import org.bouncycastle.util.Pack;
import org.bouncycastle.util.Strings;

class KeyUtils
{
    private static final BigInteger TWO = BigInteger.valueOf(2);

    static BigInteger validated(DHDomainParameters dhParams, BigInteger y)
    {
        // TLS check
        if (y.compareTo(TWO) < 0 || y.compareTo(dhParams.getP().subtract(TWO)) > 0)
        {
            throw new IllegalArgumentException("Y value is out of range");
        }

        if (dhParams.getQ() != null)
        {
            // FSM_STATE:5.10, "SP 800-56A ASSURANCES", "The module is performing SP 800-56A Assurances self-test"
            // FSM_TRANS:5.17, "CONDITIONAL TEST", "SP 800-56A ASSURANCES CHECK", "Invoke SP 800-56A Assurances test"
            if (BigInteger.ONE.equals(y.modPow(dhParams.getQ(), dhParams.getP())))
            {
                // FSM_TRANS:5.18, "SP 800-56A ASSURANCES CHECK", "CONDITIONAL TEST", "SP 800-56A Assurances test successful"
                return y;
            }
            // FSM_TRANS:5.19, "SP 800-56A ASSURANCES CHECK", "CONDITIONAL TEST", "SP 800-56A Assurances test failed"
            throw new IllegalArgumentException("Y value does not appear to be in correct group");
        }
        else
        {
            return y;         // we can't really validate without Q.
        }
    }

    static BigInteger validated(DSADomainParameters dsaParams, BigInteger y)
    {
        if (dsaParams != null)
        {
            // FSM_STATE:5.9, "FIPS 186-3/SP 800-89 ASSURANCES", "The module is performing FIPS 186-3/SP 800-89 Assurances self-test"
            // FSM_TRANS:5.14, "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "Invoke FIPS 186-3/SP 800-89 Assurances test"
            if (TWO.compareTo(y) <= 0 && dsaParams.getP().subtract(TWO).compareTo(y) >= 0
                && BigInteger.ONE.equals(y.modPow(dsaParams.getQ(), dsaParams.getP())))
            {
                 // FSM_TRANS:5.15, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test successful"
                return y;
            }
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Y value does not appear to be in correct group");
        }
        else
        {
            return y;         // we can't validate without params, fortunately we can't use the key either...
        }
    }

    static BigInteger validated(BigInteger modulus, BigInteger publicExponent)
    {
        // FSM_STATE:5.9, "FIPS 186-3/SP 800-89 ASSURANCES", "The module is performing FIPS 186-3/SP 800-89 Assurances self-test"
        // FSM_TRANS:5.14, "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "Invoke FIPS 186-3/SP 800-89 Assurances test"
        if ((publicExponent.intValue() & 1) == 0)
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("RSA publicExponent is even");
        }

        return validatedModulus(modulus);
    }

    static BigInteger validatedModulus(BigInteger modulus)
    {
        // if there is already a marker for this modulus it has already been validated, or we've already loaded it with a private key.
        // skip the tests
        if (!AsymmetricRSAKey.isAlreadySeen(modulus))
        {
            if ((modulus.intValue() & 1) == 0)
            {
                // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
                throw new IllegalArgumentException("RSA modulus is even");
            }

            // the value is the product of the 132 smallest primes from 3 to 751
            if (!modulus.gcd(new BigInteger("145188775577763990151158743208307020242261438098488931355057091965" +
                "931517706595657435907891265414916764399268423699130577757433083166" +
                "651158914570105971074227669275788291575622090199821297575654322355" +
                "049043101306108213104080801056529374892690144291505781966373045481" +
                "8359472391642885328171302299245556663073719855")).equals(BigInteger.ONE))
            {
                // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
                throw new IllegalArgumentException("RSA modulus has a small prime factor");
            }

            // Use the same iterations as if we were testing a candidate p or q value with error probability 2^-100
            int bits = modulus.bitLength() / 2;
            int iterations = bits >= 1536 ? 3
                : bits >= 1024 ? 4
                : bits >= 512 ? 7
                : 50;

            // SP 800-89 requires use of an approved DRBG.
            SecureRandom testRandom = FipsDRBG.SHA256.fromEntropySource(new SecureRandom(), false)
                .build(Pack.longToBigEndian(System.currentTimeMillis()), false, Strings.toByteArray(Thread.currentThread().toString()));

            Primes.MROutput mr = Primes.enhancedMRProbablePrimeTest(modulus, testRandom, iterations);
            if (!mr.isProvablyComposite())
            {
                // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
                throw new IllegalArgumentException("RSA modulus is not composite");
            }
            if (!mr.isNotPrimePower())
            {
                // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
                throw new IllegalArgumentException("RSA modulus is a power of a prime");
            }
        }
        // FSM_TRANS:5.15, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test successful"

        return modulus;
    }

    static ECPoint validated(ECCurve c, ECPoint q)
    {
        // FSM_STATE:5.9, "FIPS 186-3/SP 800-89 ASSURANCES", "The module is performing FIPS 186-3/SP 800-89 Assurances self-test"
        // FSM_TRANS:5.14, "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "Invoke FIPS 186-3/SP 800-89 Assurances test"
        if (q == null)
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point has null value");
        }

        q = ECAlgorithms.importPoint(c, q).normalize();

        if (q.isInfinity())
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point at infinity");
        }

        if (!q.isValid())
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point not on curve");
        }

        // FSM_TRANS:5.15, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test successful"
        return q;
    }

    static ECPoint validated(ECCurve c, byte[] encodedPoint)
    {
        // FSM_STATE:5.9, "FIPS 186-3/SP 800-89 ASSURANCES", "The module is performing FIPS 186-3/SP 800-89 Assurances self-test"
        // FSM_TRANS:5.14, "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "Invoke FIPS 186-3/SP 800-89 Assurances test"
        if (encodedPoint == null)
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point encoding has null value");
        }

        ECPoint q = c.decodePoint(encodedPoint);

        if (q == null)
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point has null value");
        }

        q = q.normalize();

        if (q.isInfinity())
        {
            // FSM_TRANS:5.16, "FIPS 186-3/SP 800-89 ASSURANCES CHECK", "CONDITIONAL TEST", "FIPS 186-3/SP 800-89 Assurances test failed"
            throw new IllegalArgumentException("Point at infinity");
        }

        return q;
    }

    static boolean isNotNull(ASN1Encodable parameters)
    {
        return parameters != null && !DERNull.INSTANCE.equals(parameters.toASN1Primitive());
    }

    static X962Parameters buildCurveParameters(ECDomainParameters curveParams)
    {
        X962Parameters          params;

        if (curveParams instanceof NamedECDomainParameters)
        {
            params = new X962Parameters(((NamedECDomainParameters)curveParams).getID());
        }
        else if (curveParams instanceof ECImplicitDomainParameters)
        {
            params = new X962Parameters(DERNull.INSTANCE);
        }
        else
        {
            X9ECParameters ecP = new X9ECParameters(
                curveParams.getCurve(),
                curveParams.getG(),
                curveParams.getN(),
                curveParams.getH(),
                curveParams.getSeed());

            params = new X962Parameters(ecP);
        }

        return params;
    }

    static int getOrderBitLength(ECDomainParameters curveParams)
    {
        return curveParams.getN().bitLength();
    }

    static boolean isDHPKCSParam(ASN1Encodable params)
    {
        ASN1Sequence seq = ASN1Sequence.getInstance(params);

        if (seq.size() == 2)
        {
            return true;
        }

        if (seq.size() > 3)
        {
            return false;
        }

        ASN1Integer l = ASN1Integer.getInstance(seq.getObjectAt(2));
        ASN1Integer p = ASN1Integer.getInstance(seq.getObjectAt(0));

        if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0)
        {
            return false;
        }

        return true;
    }

    static byte[] getEncodedInfo(ASN1Object info)
    {
         try
         {
             return info.getEncoded(ASN1Encoding.DER);
         }
         catch (Exception e)
         {
             return null;
         }
    }

    static byte[] getEncodedSubjectPublicKeyInfo(AlgorithmIdentifier algId, ASN1Encodable pubKey)
    {
         try
         {
             SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(algId, pubKey.toASN1Primitive());

             return getEncodedInfo(info);
         }
         catch (Exception e)
         {
             return null;
         }
    }

    static byte[] getEncodedPrivateKeyInfo(AlgorithmIdentifier algId, ASN1Encodable privKey)
    {
         try
         {
             PrivateKeyInfo info = new PrivateKeyInfo(algId, privKey.toASN1Primitive());

             return getEncodedInfo(info);
         }
         catch (Exception e)
         {
             return null;
         }
    }

    static byte[] getEncodedPrivateKeyInfo(AlgorithmIdentifier algId, ASN1Encodable privKey, ASN1Set attributes, byte[] publicKey)
    {
         try
         {
             PrivateKeyInfo info = new PrivateKeyInfo(algId, privKey.toASN1Primitive(), attributes, publicKey);

             return getEncodedInfo(info);
         }
         catch (Exception e)
         {
             return null;
         }
    }

    static void checkDestroyed(Destroyable destroyable)
    {
        if (destroyable.isDestroyed())
        {
            throw new IllegalStateException("key has been destroyed");
        }
    }

    static void checkPermission(final Permission keyPermission)
    {
        final SecurityManager securityManager = System.getSecurityManager();

        if (securityManager != null)
        {
            securityManager.checkPermission(keyPermission);
        }
    }

    static boolean isValidPrefix(byte[] prefix, byte[] encoding)
    {
        if (encoding.length < prefix.length)
        {
            return !isValidPrefix(prefix, prefix);
        }

        int nonEqual = 0;

        for (int i = 0; i != prefix.length; i++)
        {
            nonEqual |= (prefix[i] ^ encoding[i]);
        }

        return nonEqual == 0;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy