public CryptEngineImpl(Context ctx) throws Exception {

    // Получаем действующее хранилище
    IKeyStorage storage = KeyStorageFactory.getKeyStorage(ctx);

    Log.v("TFORWARD.CryptEngineImpl", "Decoding public key...");
    byte[] publicKey = Base64.decode(storage.getKey(IKeyStorage.PUBLIC_KEY_TYPE), Base64.DEFAULT);

    Log.v("TFORWARD.CryptEngineImpl", "Decoding ASN1 Structure");
    ASN1InputStream asnStream = new ASN1InputStream(publicKey);

    ASN1Sequence sequence = null;
    try {
      Log.v("TFORWARD.CryptEngineImpl", "Reading ASN1 Sequence");
      sequence = (ASN1Sequence) asnStream.readObject();
    } finally {
      asnStream.close();
    }

    Log.v("TFORWARD.CryptEngineImpl", "Creating certificate. " + sequence.size());
    Certificate certificate = Certificate.getInstance(sequence);
    SubjectPublicKeyInfo publicKeyInfo = certificate.getSubjectPublicKeyInfo();

    RSAPublicKey publicKeyStructure = RSAPublicKey.getInstance(publicKeyInfo.parsePublicKey());
    BigInteger mod = publicKeyStructure.getModulus();
    BigInteger pubExp = publicKeyStructure.getPublicExponent();

    publicRsaKey = new RSAKeyParameters(false, mod, pubExp);

    // ------------------------ PRIVATE KEY --------------------------------
    byte[] privateKeyData =
        Base64.decode(storage.getKey(IKeyStorage.SECRET_KEY_TYPE), Base64.DEFAULT);
    asnStream = new ASN1InputStream(privateKeyData);

    ASN1Sequence asnSequence = null;
    try {
      asnSequence = (ASN1Sequence) asnStream.readObject();
    } finally {
      asnStream.close();
    }

    RSAPrivateKey privateKey = RSAPrivateKey.getInstance(asnSequence);
    privateRsaKey =
        new RSAPrivateCrtKeyParameters(
            privateKey.getModulus(),
            privateKey.getPublicExponent(),
            privateKey.getPrivateExponent(),
            privateKey.getPrime1(),
            privateKey.getPrime2(),
            privateKey.getExponent1(),
            privateKey.getExponent2(),
            privateKey.getCoefficient());

    RSAEngine engine = new RSAEngine();
    digest = new MD5Digest();
    cipher = new PKCS1Encoding(engine);
  }
  private PemObject createPemObject(
      Object obj, String algorithm, char[] password, SecureRandom random) throws IOException {
    if (obj instanceof KeyPair) {
      return createPemObject(((KeyPair) obj).getPrivate(), algorithm, password, random);
    }

    String type = null;
    byte[] keyData = null;

    if (obj instanceof RSAPrivateCrtKey) {
      type = "RSA PRIVATE KEY";

      RSAPrivateCrtKey k = (RSAPrivateCrtKey) obj;

      org.bouncycastle.asn1.pkcs.RSAPrivateKey keyStruct =
          new org.bouncycastle.asn1.pkcs.RSAPrivateKey(
              k.getModulus(),
              k.getPublicExponent(),
              k.getPrivateExponent(),
              k.getPrimeP(),
              k.getPrimeQ(),
              k.getPrimeExponentP(),
              k.getPrimeExponentQ(),
              k.getCrtCoefficient());

      // convert to bytearray
      keyData = keyStruct.getEncoded();
    } else if (obj instanceof DSAPrivateKey) {
      type = "DSA PRIVATE KEY";

      DSAPrivateKey k = (DSAPrivateKey) obj;
      DSAParams p = k.getParams();
      ASN1EncodableVector v = new ASN1EncodableVector();

      v.add(new DERInteger(0));
      v.add(new DERInteger(p.getP()));
      v.add(new DERInteger(p.getQ()));
      v.add(new DERInteger(p.getG()));

      BigInteger x = k.getX();
      BigInteger y = p.getG().modPow(x, p.getP());

      v.add(new DERInteger(y));
      v.add(new DERInteger(x));

      keyData = new DERSequence(v).getEncoded();
    } else if (obj instanceof PrivateKey && "ECDSA".equals(((PrivateKey) obj).getAlgorithm())) {
      type = "EC PRIVATE KEY";

      PrivateKeyInfo privInfo =
          PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(((PrivateKey) obj).getEncoded()));

      keyData = privInfo.parsePrivateKey().toASN1Primitive().getEncoded();
    }

    if (type == null || keyData == null) {
      // TODO Support other types?
      throw new IllegalArgumentException("Object type not supported: " + obj.getClass().getName());
    }

    String dekAlgName = Strings.toUpperCase(algorithm);

    // Note: For backward compatibility
    if (dekAlgName.equals("DESEDE")) {
      dekAlgName = "DES-EDE3-CBC";
    }

    int ivLength = dekAlgName.startsWith("AES-") ? 16 : 8;

    byte[] iv = new byte[ivLength];
    random.nextBytes(iv);

    byte[] encData = PEMUtilities.crypt(true, provider, keyData, password, dekAlgName, iv);

    List headers = new ArrayList(2);

    headers.add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
    headers.add(new PemHeader("DEK-Info", dekAlgName + "," + getHexEncoded(iv)));

    return new PemObject(type, headers, encData);
  }