RSA公钥在android中的实现

RSA公钥在android中的实现,android,rsa,bouncycastle,phpseclib,pidcrypt,Android,Rsa,Bouncycastle,Phpseclib,Pidcrypt,我已经在php、javascript和android应用程序中使用库实现了RSA加密: phpseclib用于php端 pidcrypt用于javascript 用于anrdroid服务提供商的BounchryCastle版本(bcprov-jdk14-151) 我的加密机制如下: user->request->publickey ->server->generate(publickey,privatekey) and save private key into

我已经在php、javascript和android应用程序中使用库实现了RSA加密:

  • phpseclib用于php端

  • pidcrypt用于javascript

  • 用于anrdroid服务提供商的BounchryCastle版本(bcprov-jdk14-151)

  • 我的加密机制如下:

    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密钥生成

    $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解密代码

    $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-----
    
  • 来自服务器和服务器的请求密钥生成公钥和私钥,并将公钥模数指数发送到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);
    
  • 这段代码无法解密消息,我从PHP端得到这个错误

    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;
     }
    
  • 第二个场景是获取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);
    
  • 有了这个,我得到了一个错误

    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编码解码来指导我---

  • 第三种情况是

     final Reader reader = new StringReader(rsaPublicKeyString);
     PemReader pemReader = new PemReader(reader);
     PemObject pemObject= pemReader.readPemObject();
     pemReader.close();
     AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(pemObject.getContent());
    
  • 我忘了那个错误

     unable to cast pemObject to asymmetric ( not sure but something like that )
    
    我甚至尝试了下面链接中的一些代码,但我得到了不同的错误


    请查看代码并帮助我。

    在几个小时后使用指数和模数 我已经成功地在android应用程序和php服务器之间加密和解密数据 这是一个可能对某些人有用的解决方案

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

    所以我使用了APACHEcommons-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差异

    谢谢