android中的RSA公钥实现

时间:2014-09-15 05:47:10

标签: android rsa bouncycastle phpseclib pidcrypt

我已经在php,javascript和android app中使用库实现了RSA加密:

  1. phpseclib for php side

  2. pidcrypt for javascript

  3. bouncrycastle版本(bcprov-jdk14-151) for anrdroid serviceprovider

  4. 我的加密机制如下:

    user->request->publickey
         ->server->generate(publickey,privatekey) and save private key into Database
         ->server->sendpublickey->user
         ->user->encryptdata->send->server->decrypt
    

    然而,这种机制在javascript和php加密和解密之间工作正常但在服务器发送公钥时在android平台中。它无法解密公钥。

    现在我已经测试了这个

    的不同场景

    PHP KeyGenerating

    $rsa = new Crypt_RSA();
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
    $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
    define('CRYPT_RSA_EXPONENT', 65537);
    extract($rsa->createKey(1024));
    

    PHP DecryptingCode

    $rsa = new Crypt_RSA();
    $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
    $rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
    $rsa->loadKey($pri);
    $binaryCiphertext=base64_decode($encrypted);
    $strBase64DecryptedData=$rsa->decrypt($binaryCiphertext);
    $plaintText = base64_decode($strBase64DecryptedData);
    

    因为我的公钥是。

    -----BEGIN RSA PUBLIC KEY-----
    MIGJAoGBALrBdN8F83hT2+pBsAwiNx+v3FWp51IdEElE8UvVhfZYmePbitpzLcJi
    jZ4/tvRFXJGhqa3PKPUQkH2F4VrHruA2kNceiL/Btywc9oM+tDMeX1jcRKwXwK1k
    KdccKwn0qywG6YxQuqWQIotOfV+IIuhcHdaHBl6CZ05/cBo6AlMlAgMBAAE=
    -----END RSA PUBLIC KEY-----
    
    1. 来自服务器和服务器的请求密钥生成公钥和私钥,并将公钥 MODULUS EXPONENT 发送到Android应用程序并应用此代码:

      RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(mod,exp);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA","BS");
      PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
      Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BS");
      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
      byte[] encryptedBytes = cipher.doFinal(plaintText.getBytes());
      byte[] encodedBytes = org.bouncycastle.util.encoders.Base64.encode(encryptedBytes);
      String encryptedData = new String(encodedBytes);
      
    2. 此代码无法解密消息,我从PHP SIDE

      收到此错误
      Decryption error in /security/RSA.php on line **2493**
      

      RSA.php 2493代码

       if (ord($em[0]) != 0 || ord($em[1]) > 2) {
           user_error('Decryption error');
           return false;
       }
      
      1. 第二种情况是获取publick键字符串并解析它

        byte[] keyBytes =   Base64.decode(keyString, Base64.DEFAULT);
        String rsaPublicKeyString = new String(keyBytes); 
        String sliceKeyHeader = rsaPublicKeyString.replaceAll("(-+BEGIN RSA PUBLIC KEY-+\\r?\\n|-+END RSA PUBLICKEY-+\\r?\\n?)", "");
        byte[] encodedDER = Base64.encode(sliceKeyHeader.getBytes(),Base64.DEFAULT);
        
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedDER);
        KeyFactory kf = KeyFactory.getInstance("RSA","BC");
        PublicKey pkPublic = (PublicKey) kf.generatePublic(publicKeySpec);
        
      2. 有了这个我得到错误

        java.security.spec.InvalidKeySpecException: 
        java.lang.ClassCastException: com.android.org.bouncycastle.asn1.DERApplicationSpecific
        cannot be cast to com.android.org.bouncycastle.asn1.ASN1Sequence
        

        我知道编码的公钥是DER编码的,但我仍然不知道该怎么做 ---我认为有人可以用DER编码解码来指导我---

        1. 第三种情况是

           final Reader reader = new StringReader(rsaPublicKeyString);
           PemReader pemReader = new PemReader(reader);
           PemObject pemObject= pemReader.readPemObject();
           pemReader.close();
           AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(pemObject.getContent());
          
        2. 我忘记了它的错误

           unable to cast pemObject to asymmetric ( not sure but something like that )
          

          我甚至尝试了以下链接中的一些代码,但我遇到了不同的错误。

          RSA Android Encrypt / RSA PHP Decrypt PhpSeclib <-> BouncyCastle RSA

          请查看代码并帮助我。

1 个答案:

答案 0 :(得分:2)

确定几个小时后, EXPONENT MODULUS 我已成功加密和解密Android应用程序和PHP服务器之间的数据 这是一个可能对某人有用的解决方案

我的错误是,当密码数据准备编码时,我正在使用 JAVA 内部BASE64类生成x2大小的编码数据,php有不同的解码和编码机制(我不太确定只是一个猜测)

所以无效我使用 APACHE commons-codec-1.8库 这是正确的代码

RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(mod,exp);
KeyFactory keyFactory = KeyFactory.getInstance("RSA","BS");
PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BS");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));//
byte[] coded = Base64.encodeBase64(encryptedBytes);  //used library encode decode
String encryptedData = new String(encodedBytes);

倒数第二行是将密码二进制数据编码为BASE64

我将了解有关JAVA和PHP之间BASE64差异的更多信息

由于