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);
  }
  /**
   * Create a public key from the passed in SubjectPublicKeyInfo
   *
   * @param keyInfo the SubjectPublicKeyInfo containing the key data
   * @return the appropriate key parameter
   * @throws IOException on an error decoding the key
   */
  public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException {
    AlgorithmIdentifier algId = keyInfo.getAlgorithm();

    if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
        || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa)) {
      RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());

      return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
    } else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber)) {
      DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());

      BigInteger y = dhPublicKey.getY().getValue();

      DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());

      BigInteger p = dhParams.getP().getValue();
      BigInteger g = dhParams.getG().getValue();
      BigInteger q = dhParams.getQ().getValue();

      BigInteger j = null;
      if (dhParams.getJ() != null) {
        j = dhParams.getJ().getValue();
      }

      DHValidationParameters validation = null;
      DHValidationParms dhValidationParms = dhParams.getValidationParms();
      if (dhValidationParms != null) {
        byte[] seed = dhValidationParms.getSeed().getBytes();
        BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();

        // TODO Check pgenCounter size?

        validation = new DHValidationParameters(seed, pgenCounter.intValue());
      }

      return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
    } else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement)) {
      DHParameter params = DHParameter.getInstance(algId.getParameters());
      ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey();

      BigInteger lVal = params.getL();
      int l = lVal == null ? 0 : lVal.intValue();
      DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);

      return new DHPublicKeyParameters(derY.getValue(), dhParams);
    }
    // BEGIN android-removed
    // else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
    // {
    //     ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
    //     ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
    //
    //     return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
    //         params.getP(), params.getG()));
    // }
    // END android-removed
    else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
        || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1)) {
      ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey();
      ASN1Encodable de = algId.getParameters();

      DSAParameters parameters = null;
      if (de != null) {
        DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
        parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
      }

      return new DSAPublicKeyParameters(derY.getValue(), parameters);
    } else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey)) {
      X962Parameters params = X962Parameters.getInstance(algId.getParameters());

      X9ECParameters x9;
      if (params.isNamedCurve()) {
        ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) params.getParameters();
        x9 = ECNamedCurveTable.getByOID(oid);
      } else {
        x9 = X9ECParameters.getInstance(params.getParameters());
      }

      ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
      X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);

      // TODO We lose any named parameters here

      ECDomainParameters dParams =
          new ECDomainParameters(x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());

      return new ECPublicKeyParameters(derQ.getPoint(), dParams);
    } else {
      throw new RuntimeException("algorithm identifier in key not recognised");
    }
  }