FileDocCategorySizeDatePackage
EncryptedPrivateKeyInfo.javaAPI DocAndroid 1.5 API22096Wed May 06 22:41:02 BST 2009javax.crypto

EncryptedPrivateKeyInfo

public class EncryptedPrivateKeyInfo extends Object
This class implements the {@code EncryptedPrivateKeyInfo} ASN.1 type as specified in PKCS #8 - Private-Key Information Syntax Standard.

The definition of ASN.1 is as follows:

EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm AlgorithmIdentifier,
encryptedData OCTET STRING }
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL }
since
Android 1.0

Fields Summary
private String
algName
private final AlgorithmParameters
algParameters
private final byte[]
encryptedData
private String
oid
private volatile byte[]
encoded
private static final byte[]
nullParam
private static final org.apache.harmony.security.asn1.ASN1Sequence
asn1
private static final org.apache.harmony.security.asn1.ASN1SetOf
ASN1Attributes
private static final org.apache.harmony.security.asn1.ASN1Sequence
ASN1PrivateKeyInfo
Constructors Summary
public EncryptedPrivateKeyInfo(byte[] encoded)
Creates an {@code EncryptedPrivateKeyInfo} instance from its encoded representation by parsing it.

param
encoded the encoded representation of this object
throws
IOException if parsing the encoded representation fails.
throws
NullPointerException if {@code encoded} is {@code null}.
since
Android 1.0

        if (encoded == null) {
            throw new NullPointerException(Messages.getString("crypto.22")); //$NON-NLS-1$
        }
        this.encoded = new byte[encoded.length];
        System.arraycopy(encoded, 0, this.encoded, 0, encoded.length);
        Object[] values;
            
        values = (Object[])asn1.decode(encoded);

        AlgorithmIdentifier aId = (AlgorithmIdentifier) values[0];

        algName = aId.getAlgorithm();
        // algName == oid now
        boolean mappingExists = mapAlgName();
        // algName == name from map oid->name if mapping exists, or
        // algName == oid if mapping does not exist

        AlgorithmParameters aParams = null;
        byte[] params = aId.getParameters();
        if (params != null && !isNullValue(params)) {
            try {
                aParams = AlgorithmParameters.getInstance(algName);
                aParams.init(aId.getParameters());
                if (!mappingExists) {
                    algName = aParams.getAlgorithm();
                }
            } catch (NoSuchAlgorithmException e) {
            }
        }
        algParameters = aParams;

        encryptedData = (byte[]) values[1];
    
public EncryptedPrivateKeyInfo(String encrAlgName, byte[] encryptedData)
Creates an {@code EncryptedPrivateKeyInfo} instance from an algorithm name and its encrypted data.

param
encrAlgName the name of an algorithm.
param
encryptedData the encrypted data.
throws
NoSuchAlgorithmException if the {@code encrAlgName} is not a supported algorithm.
throws
NullPointerException if {@code encrAlgName} or {@code encryptedData} is {@code null}.
throws
IllegalArgumentException if {@code encryptedData} is empty.
since
Android 1.0

        if (encrAlgName == null) {
            throw new NullPointerException(Messages.getString("crypto.23")); //$NON-NLS-1$
        }
        this.algName = encrAlgName;
        if (!mapAlgName()) {
            throw new NoSuchAlgorithmException(Messages.getString("crypto.24", this.algName)); //$NON-NLS-1$
        }
        if (encryptedData == null) {
            throw new NullPointerException(
                    Messages.getString("crypto.25")); //$NON-NLS-1$
        }
        if (encryptedData.length == 0) {
            throw new IllegalArgumentException(Messages.getString("crypto.26")); //$NON-NLS-1$
        }
        this.encryptedData = new byte[encryptedData.length];
        System.arraycopy(encryptedData, 0,
                this.encryptedData, 0, encryptedData.length);
        this.algParameters = null;
    
public EncryptedPrivateKeyInfo(AlgorithmParameters algParams, byte[] encryptedData)
Creates an {@code EncryptedPrivateKeyInfo} instance from the encryption algorithm parameters an its encrypted data.

param
algParams the encryption algorithm parameters.
param
encryptedData the encrypted data.
throws
NoSuchAlgorithmException if the algorithm name of the specified {@code algParams} parameter is not supported.
throws
NullPointerException if {@code algParams} or {@code encryptedData} is {@code null}.
since
Android 1.0

        if (algParams == null) {
            throw new NullPointerException(Messages.getString("crypto.27")); //$NON-NLS-1$
        }
        this.algParameters = algParams;
        if (encryptedData == null) {
            throw new NullPointerException(
                    Messages.getString("crypto.25")); //$NON-NLS-1$
        }
        if (encryptedData.length == 0) {
            throw new IllegalArgumentException(Messages.getString("crypto.26")); //$NON-NLS-1$
        }
        this.encryptedData = new byte[encryptedData.length];
        System.arraycopy(encryptedData, 0,
                this.encryptedData, 0, encryptedData.length);
        this.algName = this.algParameters.getAlgorithm();
        if (!mapAlgName()) {
            throw new NoSuchAlgorithmException(Messages.getString("crypto.24", this.algName)); //$NON-NLS-1$
        }
    
Methods Summary
public java.lang.StringgetAlgName()
Returns the name of the encryption algorithm.

return
the name of the encryption algorithm.
since
Android 1.0

        return algName;
    
public java.security.AlgorithmParametersgetAlgParameters()
Returns the parameters used by the encryption algorithm.

return
the parameters used by the encryption algorithm.
since
Android 1.0

        return algParameters;
    
public byte[]getEncoded()
Returns the ASN.1 encoded representation of this object.

return
the ASN.1 encoded representation of this object.
throws
IOException if encoding this object fails.
since
Android 1.0

        if (encoded == null) {
            // Generate ASN.1 encoding:
            encoded = asn1.encode(this);
        }
        byte[] ret = new byte[encoded.length];
        System.arraycopy(encoded, 0, ret, 0, encoded.length);
        return ret;
    
public byte[]getEncryptedData()
Returns the encrypted data of this key.

return
the encrypted data of this key, each time this method is called a new array is returned.
since
Android 1.0

        byte[] ret = new byte[encryptedData.length];
        System.arraycopy(encryptedData, 0, ret, 0, encryptedData.length);
        return ret;
    
public java.security.spec.PKCS8EncodedKeySpecgetKeySpec(java.security.Key decryptKey, java.lang.String providerName)
Returns the {@code PKCS8EncodedKeySpec} object extracted from the encrypted data.

param
decryptKey the key to decrypt the encrypted data with.
param
providerName the name of a provider whose cipher implementation should be used.
return
the extracted {@code PKCS8EncodedKeySpec}.
throws
NoSuchProviderException if no provider with {@code providerName} can be found.
throws
NoSuchAlgorithmException if no usable cipher can be found to decrypt the encrypted data.
throws
InvalidKeyException if {@code decryptKey} is not usable to decrypt the encrypted data.
throws
NullPointerException if {@code decryptKey} or {@code providerName} is {@code null} .
since
Android 1.0

        if (decryptKey == null) {
            throw new NullPointerException(Messages.getString("crypto.2A")); //$NON-NLS-1$
        }
        if (providerName == null) {
            throw new NullPointerException(
                    Messages.getString("crypto.2B")); //$NON-NLS-1$
        }
        try {
            Cipher cipher = Cipher.getInstance(algName, providerName);
            if (algParameters == null) {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey, algParameters);
            }
            byte[] decryptedData = cipher.doFinal(encryptedData);
            try {
                ASN1PrivateKeyInfo.verify(decryptedData);
            } catch (IOException e1) {
                throw new InvalidKeyException(
                        Messages.getString("crypto.29")); //$NON-NLS-1$
            }
            return new PKCS8EncodedKeySpec(decryptedData);
        } catch (NoSuchPaddingException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (InvalidAlgorithmParameterException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (IllegalStateException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (IllegalBlockSizeException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (BadPaddingException e) {
            throw new InvalidKeyException(e.getMessage());
        }
    
public java.security.spec.PKCS8EncodedKeySpecgetKeySpec(java.security.Key decryptKey, java.security.Provider provider)
Returns the {@code PKCS8EncodedKeySpec} object extracted from the encrypted data.

param
decryptKey the key to decrypt the encrypted data with.
param
provider the provider whose cipher implementation should be used.
return
the extracted {@code PKCS8EncodedKeySpec}.
throws
NoSuchAlgorithmException if no usable cipher can be found to decrypt the encrypted data.
throws
InvalidKeyException if {@code decryptKey} is not usable to decrypt the encrypted data.
throws
NullPointerException if {@code decryptKey} or {@code provider} is {@code null}.
since
Android 1.0

        if (decryptKey == null) {
            throw new NullPointerException(Messages.getString("crypto.2A")); //$NON-NLS-1$
        }
        if (provider == null) {
            throw new NullPointerException(Messages.getString("crypto.2C")); //$NON-NLS-1$
        }
        try {
            Cipher cipher = Cipher.getInstance(algName, provider);
            if (algParameters == null) {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey, algParameters);
            }
            byte[] decryptedData = cipher.doFinal(encryptedData);
            try {
                ASN1PrivateKeyInfo.verify(decryptedData);
            } catch (IOException e1) {
                throw new InvalidKeyException(
                        Messages.getString("crypto.29")); //$NON-NLS-1$
            }
            return new PKCS8EncodedKeySpec(decryptedData);
        } catch (NoSuchPaddingException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (InvalidAlgorithmParameterException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (IllegalStateException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (IllegalBlockSizeException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (BadPaddingException e) {
            throw new InvalidKeyException(e.getMessage());
        }
    
public java.security.spec.PKCS8EncodedKeySpecgetKeySpec(javax.crypto.Cipher cipher)
Returns the {@code PKCS8EncodedKeySpec} object extracted from the encrypted data.

The cipher must be initialize in either {@code Cipher.DECRYPT_MODE} or {@code Cipher.UNWRAP_MODE} with the same parameters and key used for encrypting this.

param
cipher the cipher initialized for decrypting the encrypted data.
return
the extracted {@code PKCS8EncodedKeySpec}.
throws
InvalidKeySpecException if the specified cipher is not suited to decrypt the encrypted data.
throws
NullPointerException if {@code cipher} is {@code null}.
since
Android 1.0

        if (cipher == null) {
            throw new NullPointerException(Messages.getString("crypto.28")); //$NON-NLS-1$
        }
        try {
            byte[] decryptedData = cipher.doFinal(encryptedData);
            try {
                ASN1PrivateKeyInfo.verify(decryptedData);
            } catch (IOException e1) {
                throw new InvalidKeySpecException(
                        Messages.getString("crypto.29")); //$NON-NLS-1$
            }
            return new PKCS8EncodedKeySpec(decryptedData);
        } catch (IllegalStateException e) {
            throw new InvalidKeySpecException(e.getMessage());
        } catch (IllegalBlockSizeException e) {
            throw new InvalidKeySpecException(e.getMessage());
        } catch (BadPaddingException e) {
            throw new InvalidKeySpecException(e.getMessage());
        }
    
public java.security.spec.PKCS8EncodedKeySpecgetKeySpec(java.security.Key decryptKey)
Returns the {@code PKCS8EncodedKeySpec} object extracted from the encrypted data.

param
decryptKey the key to decrypt the encrypted data with.
return
the extracted {@code PKCS8EncodedKeySpec}.
throws
NoSuchAlgorithmException if no usable cipher can be found to decrypt the encrypted data.
throws
InvalidKeyException if {@code decryptKey} is not usable to decrypt the encrypted data.
throws
NullPointerException if {@code decryptKey} is {@code null}.
since
Android 1.0

        if (decryptKey == null) {
            throw new NullPointerException(Messages.getString("crypto.2A")); //$NON-NLS-1$
        }
        try {
            Cipher cipher = Cipher.getInstance(algName);
            if (algParameters == null) {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, decryptKey, algParameters);
            }
            byte[] decryptedData = cipher.doFinal(encryptedData);
            try {
                ASN1PrivateKeyInfo.verify(decryptedData);
            } catch (IOException e1) {
                throw new InvalidKeyException(
                        Messages.getString("crypto.29")); //$NON-NLS-1$
            }
            return new PKCS8EncodedKeySpec(decryptedData);
        } catch (NoSuchPaddingException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (InvalidAlgorithmParameterException e) {
            throw new NoSuchAlgorithmException(e.getMessage());
        } catch (IllegalStateException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (IllegalBlockSizeException e) {
            throw new InvalidKeyException(e.getMessage());
        } catch (BadPaddingException e) {
            throw new InvalidKeyException(e.getMessage());
        }
    
private static booleanisNullValue(byte[] toCheck)

        return toCheck[0] == 5 && toCheck[1] == 0;
    
private booleanmapAlgName()

        if (AlgNameMapper.isOID(this.algName)) {
            // OID provided to the ctor
            // get rid of possible leading "OID."
            this.oid = AlgNameMapper.normalize(this.algName);
            // try to find mapping OID->algName
            this.algName = AlgNameMapper.map2AlgName(this.oid);
            // if there is no mapping OID->algName
            // set OID as algName
            if (this.algName == null) {
                this.algName = this.oid;
            }
        } else {
            String stdName = AlgNameMapper.getStandardName(this.algName);
            // Alg name provided to the ctor
            // try to find mapping algName->OID or
            // (algName->stdAlgName)->OID
            this.oid = AlgNameMapper.map2OID(this.algName);
            if (this.oid == null) {
                if (stdName == null) {
                    // no above mappings available
                    return false;
                }
                this.oid = AlgNameMapper.map2OID(stdName);
                if (this.oid == null) {
                    return false;
                }
                this.algName = stdName;
            } else if (stdName != null) {
                this.algName = stdName;
            }
        }
        return true;