Android RSA加密与解密开发总结(可以与c#的RSA加密解密互通)

来源:互联网 发布:收费av网站源码 编辑:程序博客网 时间:2024/04/30 12:35
Java中有很好的rsa加密与解密类库,同样这些类库也被迁移到了Androidapi中,但稍有不同,在java中的base64编码和解码apiAndroid稍有不同,Android只是简化了一部分操作。如下就将Android中常用的加密和解密的方法总结如下:
  1.   //设置使用何种加密算法
  2.                 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
  3.                 // 密钥位数
  4.                 keyPairGen.initialize(1024);
  5.                 // 密钥对
  6.                 KeyPair keyPair = keyPairGen.generateKeyPair();
  7.                 // 公钥
  8.                 PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  9.                 // 私钥
  10.                 PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
复制代码
以上api需要引入以下的包
  1. import java.security.Key;
  2. import java.security.KeyFactory;
  3. import java.security.KeyPair;
  4. import java.security.KeyPairGenerator;
  5. import java.security.PrivateKey;
  6. import java.security.PublicKey;
  7. import java.security.interfaces.RSAPrivateKey;
  8. import java.security.interfaces.RSAPublicKey;
  9. import java.security.spec.PKCS8EncodedKeySpec;
  10. import java.security.spec.X509EncodedKeySpec;
复制代码
为了公钥跟私钥可以传输和保存,因此可以设置为将他们转化成base64的编码,用到以下方法:
  1. /****************************************
  2.          * 函数说明:getKeyString 根据key得到64位加密字符串
  3.          * 
  4.          * @param key 密钥
  5.          * @throws Exception
  6.          * @return String 加密后的字符串
  7.          * @author 王洪贺 2013-8-21
  8.          ***************************************/
  9.         public static String getKeyString(Key key) throws Exception
  10.         {
  11.                 byte[] keyBytes = key.getEncoded();
  12.                 String s = base64Enc(keyBytes);
  13.                 return s;
  14.         }
复制代码
但加密跟解密的时候需要将base64位的编码转化为key的对象,所以用到以下两个方法:
  1. /****************************************
  2.          * 函数说明:getPublicKey 取得公钥
  3.          * 
  4.          * @param key 公钥字符串
  5.          * @throws Exception
  6.          * @return PublicKey 返回公钥
  7.          * @author 王洪贺 2013-8-21
  8.          ***************************************/
  9.         public static PublicKey getPublicKey(String key) throws Exception
  10.         {
  11.                 byte[] keyBytes;
  12.                 keyBytes = base64Dec(key);

  13.                 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  14.                 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  15.                 PublicKey publicKey = keyFactory.generatePublic(keySpec);
  16.                 return publicKey;
  17.         }

  18.         /****************************************
  19.          * 函数说明:getPrivateKey 取得私钥
  20.          * 
  21.          * @param key 私钥字符串
  22.          * @throws Exception
  23.          * @return PrivateKey 返回私钥
  24.          * @author 王洪贺 2013-8-21
  25.          ***************************************/
  26.         public static PrivateKey getPrivateKey(String key) throws Exception
  27.         {
  28.                 byte[] keyBytes;
  29.                 keyBytes = base64Dec(key);

  30.                 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
  31.                 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  32.                 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
  33.                 return privateKey;
  34.         }
复制代码
下面就是加密过程,很简单:
  1. // 实例化加解密类
  2.                 Cipher cipher = Cipher.getInstance("RSA");

  3.                 // 明文
  4.                 byte[] plainText = "明文".getBytes();

  5.                 // 加密
  6.                 cipher.init(Cipher.ENCRYPT_MODE, publicKe);
  7.   //将明文转化为根据公钥加密的密文,为byte数组格式
  8.                 byte[] enBytes = cipher.doFinal(plainText);
  9.   //为了方便传输我们可以将byte数组转化为base64的编码
  10.                 String str = base64Enc(enBytes );
复制代码
下面是解密过程,跟加密过程类似:
  1. Cipher cipher = Cipher.getInstance("RSA");
  2. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  3. //先将转为base64编码的加密后的数据转化为byte数组
  4. byte[] enBytes = base64Dec(str);
  5. //解密称为byte数组,应该为字符串数组最后转化为字符串
  6. byte[] deBytes = cipher.doFinal(enBytes);
  7. String strdecoded = new String(deBytes);
复制代码
测试结果如下,能够正常加密和解密


因为每次生成密钥需要的时间较长,所以密钥经过base64进行编码按照字符串保存了,上面的Android程序中的公钥和私钥转化后的字符串如下:
  1. String strpublicKey =
  2.         "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkh0aKknIsmF838HITg8rdA0I+HwS1huM3FGC/rJC0L0UC/DfNp9tYqNgxAoG4WgG+zNtSz2CxghfM8UaUP8eslQRuJHojuZxgy9MLC37Dm4VQaiXALoYdMU3f2593l61Ads3YHHToA4izYprm5Ng3q83QqJoQsopxysRpN274BwIDAQAB";


  3.         String strprivateKey =
  4.         "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKSHRoqSciyYXzfwchODyt0DQj4fBLWG4zcUYL+skLQvRQL8N82n21io2DECgbhaAb7M21LPYLGCF8zxRpQ/x6yVBG4keiO5nGDL0wsLfsObhVBqJcAuhh0xTd/bn3eXrUB2zdgcdOgDiLNimubk2DerzdComhCyinHKxGk3bvgHAgMBAAECgYAbnNR69z8QOvZoFgOfQNQwKZbZhC0vJhdGLDZclOKoSvKjIJ9g9ZX7mELIXupUfU6jrg/1IvbQc8v4ylmVEes5x0pSzsbhI3iuH7m5PNLXChqzAN4K1uC6qGNy9WL3lDTQJ2LV57/1S7iDLtWCfv/aseOzStUL9Znv19W6lX6YSQJBAOkW9A5niW9X0LxxbcMw+xwqDvfDv2nZWmCLqT56W+rjrUEP62fqRX2KqP+zwtUHOYwvaiQSh35TyQ+m1e+QdbMCQQC0syvPgrg2oMl+MkYy0cE2uMV+vZ6evzSaeq6BosUQsnpe/DOKTQZ5GkB+BnYMFZFF5YwkBifsXdIApb8mC/JdAj91dBuHJqUadiW4z29/7C6dApSIRRsvO1dPTxD5aq7mrdOf9WWp92MM39JJB0wmDH3zJfFWPAAKqC2otWkYTrMCQQCZ2Z8oi9y6LkXAG5/nLu354HHOijXeZV+tU1z25RYyNDO6YbKkQxaKz44vfuLNQSOyRlH+bftZ5Tui73wDMdLFAkEArVdICaxILdndxnPB/KSUFNPIoupBvjz+WhoyuXiujs2KKtojLY5DMa/LkAcW2Akr9ZwqkPVeuDcDbVQrEEyfdg==";
复制代码
根据以上的编码,可以放到其他的平台和语言中去,进行解码后得到对应的公钥和私钥,要发送消息只需要得到公钥即可,要解密消息得到私钥即可。此外,如果两个人互相发消息,需要设置两组不同的公钥和私钥,同一组公钥和私钥不能放在同一个设备中。

base64decode(key)编码是一个自定义的函数,大家完全可以自己写,我就不列出了。以上代码是我研究在java中进行加密与解密的方法,后来测试与c#通信有问题,因为c#的公钥和私钥与java的组成方式不同,需要用函数转换。自己又不太清楚如何转换,后使用一些开源的类,稍加修改,便可以与c#和java服务器互通了。附件中的公钥和私钥是c#中的公钥和私钥,大家也可以通过RSAHelper里的函数转化成自己需要的java的公钥私钥,或者可以用函数自己生成。具体不多讲,我在RSAHelper.java中的api写的很明白,若不明白的请留言。详细代码见附件:

本帖隐藏的内容

 RSATest.rar (2.1 MB, 下载次数: 81)


另外,附上自己研究c#及Android使用RSA加密解密算法的文档:
 20130823(c#中生成rsa密钥和加密和解密的方法以及java中的密钥与c#密钥互转的方法).do.doc (24.5 KB, 下载次数: 8)