Android使用RSA加密和解密的示例代码
程序员文章站
2023-12-17 08:20:46
一、公钥加密和私钥解密
/**rsa算法*/
public static final string rsa = "rsa";
/**加密方式,an...
一、公钥加密和私钥解密
/**rsa算法*/ public static final string rsa = "rsa"; /**加密方式,android的*/ // public static final string transformation = "rsa/none/nopadding"; /**加密方式,标准jdk的*/ public static final string transformation = "rsa/none/pkcs1padding"; /** 使用公钥加密 */ public static byte[] encryptbypublickey(byte[] data, byte[] publickey) throws exception { // 得到公钥对象 x509encodedkeyspec keyspec = new x509encodedkeyspec(publickey); keyfactory keyfactory = keyfactory.getinstance("rsa"); publickey pubkey = keyfactory.generatepublic(keyspec); // 加密数据 cipher cp = cipher.getinstance(transformation); cp.init(cipher.encrypt_mode, pubkey); return cp.dofinal(data); } /** 使用私钥解密 */ public static byte[] decryptbyprivatekey(byte[] encrypted, byte[] privatekey) throws exception { // 得到私钥对象 pkcs8encodedkeyspec keyspec = new pkcs8encodedkeyspec(privatekey); keyfactory kf = keyfactory.getinstance(rsa); privatekey keyprivate = kf.generateprivate(keyspec); // 解密数据 cipher cp = cipher.getinstance(transformation); cp.init(cipher.decrypt_mode, keyprivate); byte[] arr = cp.dofinal(encrypted); return arr; }
1.data是要加密的数据,如果是字符串则getbytes。publickey是公钥,privatekey是私钥。自定义密钥对测试
string data = "hello world"; try { int keylength = 1024; //生成密钥对 keypair keypair = rsautils.generatersakeypair(keylength); //获取公钥 byte[] publickey = rsautils.getpublickey(keypair); //获取私钥 byte[] privatekey = rsautils.getprivatekey(keypair); //用公钥加密 byte[] encrypt = rsautils.encryptbypublickey(data.getbytes(), publickey); log.d("tag", "加密后的数据:" + stringutils.bytearraytostring(encrypt)); //用私钥解密 byte[] decrypt = rsautils.decryptbyprivatekey(encrypt, privatekey); log.d("tag", "解密后的数据:" + new string(decrypt, "utf-8")); } catch (exception e) { e.printstacktrace(); }
2.从文件中读取公钥
string data = "hello world"; //读取公钥文件 string publickeystring = ioutils.readassetsfile(this, "rsa_public_key.pem"); //base64解码 byte[] publickey = base64utils.decodetobytes(publickeystring); try { //加密 byte[] encrypt = rsautils.encryptbypublickey(data.getbytes(), publickey); log.d("tag", "加密后的数据:" + stringutils.bytearraytostring(encrypt)); // //读取私钥文件 // string privatekeystring = ioutils.readassetsfile(this, "rsa_private_key.pem"); // //base64解码 // byte[] privatekey = base64utils.decodetobytes(privatekeystring); // //解密 // byte[] decrypt = rsautils.decryptbyprivatekey(encrypt, privatekey); // log.d("tag", "解密后的数据:" + new string(decrypt, "utf-8")); } catch (exception e) { e.printstacktrace(); }
二、公钥分段加密和私钥分段解密
当加密的数据过长时,会出现javax.crypto.illegalblocksizeexception: data must not be longer than 117 bytes的异常。rsa算法规定一次加密的数据不能超过生成密钥对时的keylength/8-11,keylength一般是1024个字节,则加密的数据不能超过117个字节
/**秘钥默认长度*/ public static final int default_key_size = 1024; /**加密的数据最大的字节数,即117个字节*/ public static final int default_buffersize = (default_key_size / 8) - 11; /**当加密的数据超过default_buffersize,则使用分段加密*/ public static final byte[] default_split = "#part#".getbytes(); /** 使用公钥分段加密 */ public static byte[] encryptbypublickeyforspilt(byte[] data, byte[] publickey) throws exception{ int datalen = data.length; if (datalen <= default_buffersize) { return encryptbypublickey(data, publickey); } list<byte> allbytes = new arraylist<byte>(2048); int bufindex = 0; int subdataloop = 0; byte[] buf = new byte[default_buffersize]; for (int i = 0; i < datalen; i++) { buf[bufindex] = data[i]; if (++bufindex == default_buffersize || i == datalen - 1) { subdataloop++; if (subdataloop != 1) { for (byte b : default_split) { allbytes.add(b); } } byte[] encryptbytes = encryptbypublickey(buf, publickey); for (byte b : encryptbytes) { allbytes.add(b); } bufindex = 0; if (i == datalen - 1) { buf = null; } else { buf = new byte[math .min(default_buffersize, datalen - i - 1)]; } } } byte[] bytes = new byte[allbytes.size()]; int i = 0; for (byte b : allbytes) { bytes[i++] = b.bytevalue(); } return bytes; } /** 使用私钥分段解密 */ public static byte[] decryptbyprivatekeyforspilt(byte[] encrypted, byte[] privatekey) throws exception { int splitlen = default_split.length; if (splitlen <= 0) { return decryptbyprivatekey(encrypted, privatekey); } int datalen = encrypted.length; list<byte> allbytes = new arraylist<byte>(1024); int lateststartindex = 0; for (int i = 0; i < datalen; i++) { byte bt = encrypted[i]; boolean ismatchsplit = false; if (i == datalen - 1) { // 到data的最后了 byte[] part = new byte[datalen - lateststartindex]; system.arraycopy(encrypted, lateststartindex, part, 0, part.length); byte[] decryptpart = decryptbyprivatekey(part, privatekey); for (byte b : decryptpart) { allbytes.add(b); } lateststartindex = i + splitlen; i = lateststartindex - 1; } else if (bt == default_split[0]) { // 这个是以split[0]开头 if (splitlen > 1) { if (i + splitlen < datalen) { // 没有超出data的范围 for (int j = 1; j < splitlen; j++) { if (default_split[j] != encrypted[i + j]) { break; } if (j == splitlen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 ismatchsplit = true; } } } } else { // split只有一位,则已经匹配了 ismatchsplit = true; } } if (ismatchsplit) { byte[] part = new byte[i - lateststartindex]; system.arraycopy(encrypted, lateststartindex, part, 0, part.length); byte[] decryptpart = decryptbyprivatekey(part, privatekey); for (byte b : decryptpart) { allbytes.add(b); } lateststartindex = i + splitlen; i = lateststartindex - 1; } } byte[] bytes = new byte[allbytes.size()]; int i = 0; for (byte b : allbytes) { bytes[i++] = b.bytevalue(); } return bytes; }
测试分段加密和解密
string data = "hello world hello world hello world hello world hello world hello world hello world hello world " + "hello world hello world hello world hello world hello world hello world hello world hello world hello world " + "hello world hello world hello world hello world hello world hello world hello world hello world hello world "; log.d("tag", "要加密的数据:" + data + ", 要加密的数据长度:" + data.length()); try { //分段加密 byte[] encrypt = rsautils.encryptbypublickeyforspilt(data.getbytes(), publickey); log.d("tag", "加密后的数据:" + stringutils.bytearraytostring(encrypt)); //分段解密 byte[] decrypt = rsautils.decryptbyprivatekeyforspilt(encrypt, privatekey); log.d("tag", "解密后的数据:" + new string(decrypt, "utf-8")); } catch (exception e) { e.printstacktrace(); }
三、生成密钥对
/** 生成密钥对,即公钥和私钥。key长度是512-2048,一般为1024 */ public static keypair generatersakeypair(int keylength) throws nosuchalgorithmexception { keypairgenerator kpg = keypairgenerator.getinstance(rsa); kpg.initialize(keylength); return kpg.genkeypair(); } /** 获取公钥,打印为48-12613448136942-12272-122-913111503-126115048-12...等等一长串用-拼接的数字 */ public static byte[] getpublickey(keypair keypair) { rsapublickey rsapublickey = (rsapublickey) keypair.getpublic(); return rsapublickey.getencoded(); } /** 获取私钥,同上 */ public static byte[] getprivatekey(keypair keypair) { rsaprivatekey rsaprivatekey = (rsaprivatekey) keypair.getprivate(); return rsaprivatekey.getencoded(); }
生成公钥和私钥后,用base64编码
int keylength = 1024; try { //生成密钥对 keypair keypair = rsautils.generatersakeypair(keylength); //获取公钥 byte[] publickey = rsautils.getpublickey(keypair); log.d("tag", "公钥:" + stringutils.bytearraytostring(publickey)); //公钥用base64编码 string encodepublic = base64utils.encodetostring(publickey); log.d("tag", "base64编码的公钥:" + encodepublic); //获取私钥 byte[] privatekey = rsautils.getprivatekey(keypair); log.d("tag", "私钥:" + stringutils.bytearraytostring(privatekey)); //私钥用base64编码 string encodeprivate = base64utils.encodetostring(privatekey); log.d("tag", "base64编码的私钥:" + encodeprivate); } catch (nosuchalgorithmexception e) { e.printstacktrace(); }
其它
一、android加密的数据服务器上无法解密?
android的rsa加密方式是rsa/ecb/nopadding,而标准jdk是rsa/ecb/pkcs1padding,所以加密时要设置标准jdk的加密方式
二、base64编码。因为不同的设备对字符的处理方式不同,字符有可能处理出错,不利于传输。所以先把数据做base64编码,变成可见字符,减少出错
官方提供的base64类,base64.encode编码,base64.decode解码。用这个会有换行符,需要自定义
三、rsa是非对称加密算法。依赖于大数计算,加密速度比des慢,通常只用于加密少量数据或密钥
四、公钥加密比私钥加密块,公钥解密比私钥解密慢。加密后的数据大概是加密前的1.5倍
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。