package javax.crypto; import java.io.*; import java.security.*; import java.security.spec.*; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; /** * This class implements the EncryptedPrivateKeyInfo type * as defined in PKCS #8. *

Its ASN.1 definition is as follows: * *

 * EncryptedPrivateKeyInfo ::=  SEQUENCE {
 *     encryptionAlgorithm   AlgorithmIdentifier,
 *     encryptedData   OCTET STRING }
 * 
 * AlgorithmIdentifier  ::=  SEQUENCE  {
 *     algorithm              OBJECT IDENTIFIER,
 *     parameters             ANY DEFINED BY algorithm OPTIONAL  }
 * 
*/ public class EncryptedPrivateKeyInfo { private org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo infoObj; private AlgorithmParameters algP; /* * Constructs (i.e., parses) an EncryptedPrivateKeyInfo from * its ASN.1 encoding. * * @param encoded the ASN.1 encoding of this object. * @exception NullPointerException if the encoded is null. * @exception IOException if error occurs when parsing the ASN.1 encoding. */ public EncryptedPrivateKeyInfo( byte[] encoded) throws NullPointerException, IOException { if (encoded == null) { throw new NullPointerException("parameters null"); } ByteArrayInputStream bIn = new ByteArrayInputStream(encoded); ASN1InputStream dIn = new ASN1InputStream(bIn); infoObj = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance((ASN1Sequence)dIn.readObject()); try { algP = this.getParameters(); } catch (NoSuchAlgorithmException e) { throw new IOException("can't create parameters: " + e.toString()); } } /* * Constructs an EncryptedPrivateKeyInfo from the * encryption algorithm name and the encrypted data. *

Note: the encrypedData is cloned when constructing * this object. *

* If encryption algorithm has associated parameters use the constructor * with AlgorithmParameters as the parameter. * * @param algName algorithm name. * @param encryptedData encrypted data. * @exception NullPointerException if algName or encryptedData is null. * @exception IllegalArgumentException if encryptedData is empty, i.e. 0-length. * @exception NoSuchAlgorithmException if the specified algName is not supported. */ public EncryptedPrivateKeyInfo( String algName, byte[] encryptedData) throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException { if (algName == null || encryptedData == null) { throw new NullPointerException("parameters null"); } org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(new DERObjectIdentifier(algName), null); infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone()); algP = this.getParameters(); } /** * Constructs an EncryptedPrivateKeyInfo from the * encryption algorithm parameters and the encrypted data. *

Note: the encrypedData is cloned when constructing * this object. * * @param algParams the algorithm parameters for the encryption * algorithm. algParams.getEncoded() should return * the ASN.1 encoded bytes of the parameters field * of the AlgorithmIdentifer component of the * EncryptedPrivateKeyInfo type. * @param encryptedData encrypted data. * @exception NullPointerException if algParams or encryptedData is null. * @exception IllegalArgumentException if encryptedData is empty, i.e. 0-length. * @exception NoSuchAlgorithmException if the specified algName of the specified algParams parameter is not supported. */ public EncryptedPrivateKeyInfo( AlgorithmParameters algParams, byte[] encryptedData) throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException { if (algParams == null || encryptedData == null) { throw new NullPointerException("parameters null"); } org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = null; try { ByteArrayInputStream bIn = new ByteArrayInputStream(algParams.getEncoded()); ASN1InputStream dIn = new ASN1InputStream(bIn); kAlgId = new AlgorithmIdentifier( new DERObjectIdentifier(algParams.getAlgorithm()), dIn.readObject()); } catch (IOException e) { throw new IllegalArgumentException("error in encoding: " + e.toString()); } infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone()); algP = this.getParameters(); } /** * Returns the encryption algorithm. * * @returns the algorithm name. */ public String getAlgName() { return infoObj.getEncryptionAlgorithm().getObjectId().getId(); } private AlgorithmParameters getParameters() throws NoSuchAlgorithmException { AlgorithmParameters ap = AlgorithmParameters.getInstance(this.getAlgName()); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); try { dOut.writeObject(infoObj.getEncryptionAlgorithm().getParameters()); dOut.close(); ap.init(bOut.toByteArray()); } catch (IOException e) { throw new NoSuchAlgorithmException("unable to parse parameters"); } return ap; } /** * Returns the algorithm parameters used by the encryption algorithm. * * @returns the algorithm parameters. */ public AlgorithmParameters getAlgParameters() { return algP; } /** * Returns a copy of the encrypted data. * * @returns a copy of the encrypted data. */ public byte[] getEncryptedData() { return infoObj.getEncryptedData(); } /** * Extract the enclosed PKCS8EncodedKeySpec object from the * encrypted data and return it. * * @return the PKCS8EncodedKeySpec object. * @exception InvalidKeySpecException if the given cipher is * inappropriate for the encrypted data or the encrypted * data is corrupted and cannot be decrypted. */ public PKCS8EncodedKeySpec getKeySpec( Cipher c) throws InvalidKeySpecException { try { return new PKCS8EncodedKeySpec(c.doFinal(this.getEncryptedData())); } catch (Exception e) { throw new InvalidKeySpecException("can't get keySpec: " + e.toString()); } } /** * Returns the ASN.1 encoding of this object. * * @returns the ASN.1 encoding. * @throws IOException if error occurs when constructing its ASN.1 encoding. */ public byte[] getEncoded() throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); DEROutputStream dOut = new DEROutputStream(bOut); dOut.writeObject(infoObj); dOut.close(); return bOut.toByteArray(); } }