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

org.bouncycastle.crypto.asymmetric.AsymmetricRSAPrivateKey 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.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.security.auth.Destroyable;

import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.Algorithm;
import org.bouncycastle.crypto.AsymmetricPrivateKey;
import org.bouncycastle.crypto.internal.Permissions;

/**
 * Class for RSA private keys.
 */
public final class AsymmetricRSAPrivateKey
    extends AsymmetricRSAKey
    implements Destroyable, AsymmetricPrivateKey
{
    private final AtomicBoolean hasBeenDestroyed = new AtomicBoolean(false);

    private BigInteger publicExponent;
    private BigInteger privateExponent;
    private BigInteger p;
    private BigInteger q;
    private BigInteger dp;
    private BigInteger dq;
    private BigInteger qInv;

    private int hashCode;

    public AsymmetricRSAPrivateKey(Algorithm algorithm, BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger p, BigInteger q, BigInteger dp, BigInteger dq, BigInteger qInv)
    {
        super(algorithm, modulus);

        this.publicExponent = publicExponent;
        this.privateExponent = privateExponent;
        this.p = p;
        this.q = q;
        this.dp = dp;
        this.dq = dq;
        this.qInv = qInv;
        this.hashCode = calculateHashCode();
    }

    public AsymmetricRSAPrivateKey(Algorithm algorithm, BigInteger modulus, BigInteger privateExponent)
    {
        super(algorithm, modulus);

        this.privateExponent = privateExponent;
        this.publicExponent = BigInteger.ZERO;
        this.p = BigInteger.ZERO;
        this.q = BigInteger.ZERO;
        this.dp = BigInteger.ZERO;
        this.dq = BigInteger.ZERO;
        this.qInv = BigInteger.ZERO;
        this.hashCode = calculateHashCode();
    }

    public AsymmetricRSAPrivateKey(Algorithm algorithm, byte[] privateKeyInfoEncoding)
    {
        this(algorithm, getPrivateKeyInfo(privateKeyInfoEncoding));
    }

    public AsymmetricRSAPrivateKey(Algorithm algorithm, PrivateKeyInfo privateKeyInfo)
    {
        this(algorithm, privateKeyInfo.getPrivateKeyAlgorithm(), parsePrivateKey(privateKeyInfo));
    }

    private static PrivateKeyInfo getPrivateKeyInfo(byte[] encoding)
    {
        try
        {
            return PrivateKeyInfo.getInstance(encoding);
        }
        catch (IllegalArgumentException e)
        {
            // OpenSSL's old format, and some others - Try just the private key data.
            try
            {
                return new PrivateKeyInfo(DEF_ALG_ID, ASN1Sequence.getInstance(encoding));
            }
            catch (IOException e1)
            {
                throw new IllegalArgumentException("Unable to parse private key: " + e.getMessage(), e);
            }
        }
    }

    private static RSAPrivateKey parsePrivateKey(PrivateKeyInfo privateKeyInfo)
    {
        try
        {
            return RSAPrivateKey.getInstance(privateKeyInfo.parsePrivateKey());
        }
        catch (IOException e)
        {
            throw new IllegalArgumentException("Unable to parse private key: " + e.getMessage(), e);
        }
    }

    private AsymmetricRSAPrivateKey(Algorithm algorithm, AlgorithmIdentifier algId, RSAPrivateKey privKey)
    {
        // we're importing from an encoding, let's just make sure the modulus is actually valid.
        super(algorithm, algId, KeyUtils.validatedModulus(privKey.getModulus()));

        this.publicExponent = privKey.getPublicExponent();
        this.privateExponent = privKey.getPrivateExponent();
        this.p = privKey.getPrime1();
        this.q = privKey.getPrime2();
        this.dp = privKey.getExponent1();
        this.dq = privKey.getExponent2();
        this.qInv = privKey.getCoefficient();
        this.hashCode = calculateHashCode();
    }

    /**
     * Return the algorithm this RSA key is for.
     *
     * @return the key's algorithm.
     */
    public Algorithm getAlgorithm()
    {
        KeyUtils.checkDestroyed(this);

        return super.getAlgorithm();
    }

    /**
     * Return the modulus for this RSA key.
     *
     * @return the key's modulus.
     */
    public BigInteger getModulus()
    {
        KeyUtils.checkDestroyed(this);

        return super.getModulus();
    }

    public BigInteger getPublicExponent()
    {
        KeyUtils.checkDestroyed(this);

        return publicExponent;
    }

    public BigInteger getPrivateExponent()
    {
        checkCanRead();

        return privateExponent;
    }

    public BigInteger getP()
    {
        checkCanRead();

        return p;
    }

    public BigInteger getQ()
    {
        checkCanRead();

        return q;
    }

    public BigInteger getDP()
    {
        checkCanRead();

        return dp;
    }

    public BigInteger getDQ()
    {
        checkCanRead();

        return dq;
    }

    public BigInteger getQInv()
    {
        checkCanRead();

        return qInv;
    }

    public final byte[] getEncoded()
    {
        checkApprovedOnlyModeStatus();

        KeyUtils.checkDestroyed(this);

        KeyUtils.checkPermission(Permissions.CanOutputPrivateKey);

        return KeyUtils.getEncodedPrivateKeyInfo(rsaAlgIdentifier, new RSAPrivateKey(getModulus(), publicExponent, getPrivateExponent(), getP(), getQ(), getDP(), getDQ(), getQInv()));
    }

    public void destroy()
    {
        checkApprovedOnlyModeStatus();

        KeyUtils.checkPermission(Permissions.CanOutputPrivateKey);
        
        if (!hasBeenDestroyed.getAndSet(true))
        {
            this.privateExponent = this.publicExponent = null;
            this.p = this.q = this.dp = this.dq = this.qInv = null;
            this.hashCode = -1;

            super.zeroize();
        }
    }

    public boolean isDestroyed()
    {
        checkApprovedOnlyModeStatus();

        return hasBeenDestroyed.get();
    }

    @Override
    public boolean equals(Object o)
    {
        checkApprovedOnlyModeStatus();

        if (this == o)
        {
            return true;
        }
        if (!(o instanceof AsymmetricRSAPrivateKey))
        {
            return false;
        }

        AsymmetricRSAPrivateKey other = (AsymmetricRSAPrivateKey)o;

        if (this.isDestroyed() || other.isDestroyed())
        {
            return false;
        }

        return getModulus().equals(other.getModulus())
            && privateExponent.equals(other.privateExponent) && getPublicExponent().equals(other.getPublicExponent())
            && p.equals(other.p) && q.equals(other.q)
            && dp.equals(other.dp) && dq.equals(other.dq) && qInv.equals(other.qInv);
    }

    @Override
    public int hashCode()
    {
        checkApprovedOnlyModeStatus();

        return hashCode;
    }

    private int calculateHashCode()
    {
        int result = getModulus().hashCode();
        result = 31 * result + publicExponent.hashCode();
        result = 31 * result + privateExponent.hashCode();
        result = 31 * result + p.hashCode();
        result = 31 * result + q.hashCode();
        result = 31 * result + dp.hashCode();
        result = 31 * result + dq.hashCode();
        result = 31 * result + qInv.hashCode();
        return result;
    }

    @Override
    protected void finalize()
        throws Throwable
    {
        super.finalize();

        destroy();
    }

    private void checkCanRead()
    {
        checkApprovedOnlyModeStatus();

        KeyUtils.checkPermission(Permissions.CanOutputPrivateKey);

        KeyUtils.checkDestroyed(this);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy