Android RSA加密与解密开发总结(可以与c#的RSA加密解密互通)
来源:互联网 发布:收费av网站源码 编辑:程序博客网 时间:2024/04/30 12:35
Java中有很好的rsa加密与解密类库,同样这些类库也被迁移到了Android的api中,但稍有不同,在java中的base64编码和解码api与Android稍有不同,Android只是简化了一部分操作。如下就将Android中常用的加密和解密的方法总结如下:
- //设置使用何种加密算法
- KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
- // 密钥位数
- keyPairGen.initialize(1024);
- // 密钥对
- KeyPair keyPair = keyPairGen.generateKeyPair();
- // 公钥
- PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
- // 私钥
- PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
复制代码以上api需要引入以下的包
- import java.security.Key;
- import java.security.KeyFactory;
- import java.security.KeyPair;
- import java.security.KeyPairGenerator;
- import java.security.PrivateKey;
- import java.security.PublicKey;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
复制代码为了公钥跟私钥可以传输和保存,因此可以设置为将他们转化成base64的编码,用到以下方法:
- /****************************************
- * 函数说明:getKeyString 根据key得到64位加密字符串
- *
- * @param key 密钥
- * @throws Exception
- * @return String 加密后的字符串
- * @author 王洪贺 2013-8-21
- ***************************************/
- public static String getKeyString(Key key) throws Exception
- {
- byte[] keyBytes = key.getEncoded();
- String s = base64Enc(keyBytes);
- return s;
- }
复制代码但加密跟解密的时候需要将base64位的编码转化为key的对象,所以用到以下两个方法:
- /****************************************
- * 函数说明:getPublicKey 取得公钥
- *
- * @param key 公钥字符串
- * @throws Exception
- * @return PublicKey 返回公钥
- * @author 王洪贺 2013-8-21
- ***************************************/
- public static PublicKey getPublicKey(String key) throws Exception
- {
- byte[] keyBytes;
- keyBytes = base64Dec(key);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- PublicKey publicKey = keyFactory.generatePublic(keySpec);
- return publicKey;
- }
- /****************************************
- * 函数说明:getPrivateKey 取得私钥
- *
- * @param key 私钥字符串
- * @throws Exception
- * @return PrivateKey 返回私钥
- * @author 王洪贺 2013-8-21
- ***************************************/
- public static PrivateKey getPrivateKey(String key) throws Exception
- {
- byte[] keyBytes;
- keyBytes = base64Dec(key);
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
- return privateKey;
- }
复制代码下面就是加密过程,很简单:
- // 实例化加解密类
- Cipher cipher = Cipher.getInstance("RSA");
- // 明文
- byte[] plainText = "明文".getBytes();
- // 加密
- cipher.init(Cipher.ENCRYPT_MODE, publicKe);
- //将明文转化为根据公钥加密的密文,为byte数组格式
- byte[] enBytes = cipher.doFinal(plainText);
- //为了方便传输我们可以将byte数组转化为base64的编码
- String str = base64Enc(enBytes );
复制代码下面是解密过程,跟加密过程类似:
- Cipher cipher = Cipher.getInstance("RSA");
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- //先将转为base64编码的加密后的数据转化为byte数组
- byte[] enBytes = base64Dec(str);
- //解密称为byte数组,应该为字符串数组最后转化为字符串
- byte[] deBytes = cipher.doFinal(enBytes);
- String strdecoded = new String(deBytes);
复制代码测试结果如下,能够正常加密和解密
因为每次生成密钥需要的时间较长,所以密钥经过
base64进行编码按照字符串保存了,上面的Android程序中的公钥和私钥转化后的字符串如下:- String strpublicKey =
- "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkh0aKknIsmF838HITg8rdA0I+HwS1huM3FGC/rJC0L0UC/DfNp9tYqNgxAoG4WgG+zNtSz2CxghfM8UaUP8eslQRuJHojuZxgy9MLC37Dm4VQaiXALoYdMU3f2593l61Ads3YHHToA4izYprm5Ng3q83QqJoQsopxysRpN274BwIDAQAB";
- String strprivateKey =
- "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)