1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.openssl; 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.BufferedWriter; 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream; 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayOutputStream; 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Writer; 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger; 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.Key; 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.KeyPair; 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivateKey; 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PublicKey; 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom; 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CRLException; 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateEncodingException; 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.X509CRL; 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.X509Certificate; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.interfaces.DSAPrivateKey; 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.interfaces.RSAPrivateCrtKey; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.interfaces.RSAPrivateKey; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.Cipher; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.SecretKey; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.spec.IvParameterSpec; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.crypto.spec.SecretKeySpec; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.ASN1EncodableVector; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.ASN1InputStream; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.ASN1OutputStream; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.ASN1Sequence; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.DERInteger; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.DERSequence; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.cms.ContentInfo; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.asn1.x509.DSAParameter; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.PBEParametersGenerator; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.KeyParameter; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.jce.PKCS10CertificationRequest; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.util.encoders.Base64; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.util.encoders.Hex; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.x509.X509AttributeCertificate; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.x509.X509V2AttributeCertificate; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * General purpose writer for OpenSSL PEM objects. 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class PEMWriter 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extends BufferedWriter 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Base constructor. 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param out output stream to use. 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public PEMWriter(Writer out) 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(out); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void writeHexEncoded(byte[] bytes) 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws IOException 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytes = Hex.encode(bytes); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i != bytes.length; i++) 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write((char)bytes[i]); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void writeEncoded(byte[] bytes) 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws IOException 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char[] buf = new char[64]; 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytes = Base64.encode(bytes); 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < bytes.length; i += buf.length) 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int index = 0; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (index != buf.length) 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((i + index) >= bytes.length) 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf[index] = (char)bytes[i + index]; 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project index++; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write(buf, 0, index); 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeObject( 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object o) 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws IOException 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String type; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] encoding; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (o instanceof X509Certificate) 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "CERTIFICATE"; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((X509Certificate)o).getEncoded(); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project catch (CertificateEncodingException e) 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("Cannot encode object: " + e.toString()); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof X509CRL) 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "X509 CRL"; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((X509CRL)o).getEncoded(); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project catch (CRLException e) 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("Cannot encode object: " + e.toString()); 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof KeyPair) 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeObject(((KeyPair)o).getPrivate()); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof PrivateKey) 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArrayInputStream bIn = new ByteArrayInputStream(((Key)o).getEncoded()); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ASN1InputStream aIn = new ASN1InputStream(bIn); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project PrivateKeyInfo info = new PrivateKeyInfo((ASN1Sequence)aIn.readObject()); 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ASN1OutputStream aOut = new ASN1OutputStream(bOut); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (o instanceof RSAPrivateKey) 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "RSA PRIVATE KEY"; 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aOut.writeObject(info.getPrivateKey()); 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof DSAPrivateKey) 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "DSA PRIVATE KEY"; 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DSAParameter p = DSAParameter.getInstance(info.getAlgorithmId().getParameters()); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ASN1EncodableVector v = new ASN1EncodableVector(); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(0)); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(p.getP())); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(p.getQ())); 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(p.getG())); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger x = ((DSAPrivateKey)o).getX(); 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BigInteger y = p.getG().modPow(x, p.getP()); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(y)); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.add(new DERInteger(x)); 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aOut.writeObject(new DERSequence(v)); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("Cannot identify private key"); 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = bOut.toByteArray(); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof PublicKey) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "PUBLIC KEY"; 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((PublicKey)o).getEncoded(); 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof X509AttributeCertificate) 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "ATTRIBUTE CERTIFICATE"; 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((X509V2AttributeCertificate)o).getEncoded(); 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof PKCS10CertificationRequest) 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "CERTIFICATE REQUEST"; 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((PKCS10CertificationRequest)o).getEncoded(); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (o instanceof ContentInfo) 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = "PKCS7"; 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encoding = ((ContentInfo)o).getEncoded(); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("unknown object passed - can't encode."); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("-----BEGIN " + type + "-----"); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project writeEncoded(encoding); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("-----END " + type + "-----"); 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void writeObject( 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object o, 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String algorithm, 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char[] password, 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SecureRandom random) 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws IOException 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] salt = new byte[8]; 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project random.nextBytes(salt); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt); 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SecretKey secretKey = null; 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (algorithm.equalsIgnoreCase("DESEDE")) 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // generate key 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int keyLength = 24; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project secretKey = new SecretKeySpec(((KeyParameter)pGen.generateDerivedParameters(keyLength * 8)).getKey(), algorithm); 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("unknown algorithm in writeObject"); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] keyData = null; 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (o instanceof RSAPrivateCrtKey) 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RSAPrivateCrtKey k = (RSAPrivateCrtKey)o; 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RSAPrivateKeyStructure keyStruct = new RSAPrivateKeyStructure( 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getModulus(), 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPublicExponent(), 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPrivateExponent(), 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPrimeP(), 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPrimeQ(), 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPrimeExponentP(), 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getPrimeExponentQ(), 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project k.getCrtCoefficient()); 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // convert to bytearray 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ASN1OutputStream aOut = new ASN1OutputStream(bOut); 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aOut.writeObject(keyStruct); 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project aOut.close(); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project keyData = bOut.toByteArray(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] encData = null; 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // cipher 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding", "BC"); 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project c.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(salt)); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project encData = c.doFinal(keyData); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project catch (Exception e) 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException("exception using cipher: " + e.toString()); 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // write the data 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("-----BEGIN RSA PRIVATE KEY-----"); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("Proc-Type: 4,ENCRYPTED"); 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("DEK-Info: DES-EDE3-CBC,"); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.writeHexEncoded(salt); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.newLine(); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.writeEncoded(encData); 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.write("-----END RSA PRIVATE KEY-----"); 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 296