您的位置:首页 > 移动开发 > Android开发

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

2013-09-09 16:23 756 查看
[align=left]Java中有很好的rsa加密与解密类库,同样这些类库也被迁移到了Android的api中,但稍有不同,在java中的base64编码和解码api与Android稍有不同,Android只是简化了一部分操作。如下就将Android中常用的加密和解密的方法总结如下:[/align]

  //设置使用何种加密算法

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: