Android通过RSA加密解密实现License
1. linux下用openssl生成RSA私钥和公钥(我是在windows 7下用cygwin生成的)
(参考博客: http://blog.youkuaiyun.com/chaijunkun/article/details/7275632/)
1)首先确认系统安装了openssl。如果没安装可以使用命令:sudo apt-get install openssl
2)输入openssl命令,进入openssl的交互界面
$ openssl
OpenSSL>
3)生成RSA私钥
genrsa -out rsa_private_key.pem 1024
该命令会生成1024位的私钥,生成成功的界面如下:
OpenSSL> genrsa -out rsa_private_key.pem 1024
Generating RSA private key, 1024 bit long modulus
....++++++
.....++++++
e is 65537 (0x10001)
OpenSSL>
此时我们就可以在当前路径下看到rsa_private_key.pem文件了。
4)生成RSA公钥
输入命令rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem,并回车,
得到生成成功的结果,如下:
OpenSSL> genrsa -out rsa_private_key.pem 1024
Generating RSA private key, 1024 bit long modulus
....++++++
.....++++++
e is 65537 (0x10001)
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
writing RSA key
此时,我们可以看到一个文件名为rsa_public_key.pem的文件,如图:
打开它,可以看到-----BEGIN PUBLIC KEY-----开头,
-----END PUBLIC KEY-----结尾的没有换行的字符串,这个就是公钥。
5)把RSA私钥转换成PKCS8格式
输入命令pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt,并回车,得到生成功的结果,这个结果就是PKCS8格式的私钥,如下:
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt
Enter Encryption Password:
Verifying - Enter Encryption Password:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICoTAbBgkqhkiG9w0BBQMwDgQI8iRfyoDFI3kCAggABIICgFRPGuWBmhljGSQ6
tT0qRR8RnCpyBcp5JvzVPoqOL6qRqjQlKlqjBoEtYdUU9+daAs1yNW6pCOyQQyKV
eWurd6ls0GRikspaCfRhxMgIny5LKdMwhhJfCByjnrnKqnK+3hUeBCwu57pXRtOK
nch0IexK4OV1AfaroAwZ/w5oYalTBMePJunuzatS566q+IKLMsBtVc9NMTC2f5e2
4Wg04jkmmFPDYv9LzJCRgSMuL8Gf056ls/dpQdUwfN6ni2EoLaqEXTJo/A0K0pFb
2fhvzxOOLGn2sGtZ+SDuB65xjwNKnr2dkmm2G1A2mBR8accIo04pzOcAw3lYc9q3
NyWWw55jqCnJoZVQWz892uXEykMFXcnwW4o45Hk88Xddo3EKafME3D7Vs/3OLzPF
D978BpGsLw3Ja/jzbkQ3/r9ZkJ0wN3X0z9acnthmWpHmqQHIa4obGSlT5O62y8Vz
ZloqgWv/IfRZRT3H7+pmid8MGnMYpibiHhUFxGsoKgn1u2P1lYi8CzAlA6cTbpNp
MBqduCAumSi5JzwRG1dtYpYJ/TsYQR07AYiFfWIzW1fZtrwK/VWnSZ4+2TVkAji/
JN0VwwfETXVeuHsFIQ9AJ2wCcViCACKG7C87kCBLC4edC1R9u3te9CqNZ+kppYjY
MSTMzoTWB2d6lXI+arNvSmXvlGd7nIypjrD1r3TCNZDac3UhODUZRFxZzGAuffit
KCQiLML9ePkQzPGBSpjMW2RD1Q1sbybLh0ZwwXS86lqGpD6WfUP7ssreySchNvRX
jlm0IrUAiE80NWkCOZKbBu/r/yDSIC1gz3t9WXiKcMc5RXbqdBDJZOLb9K54duoB
1nwBAkw=
-----END ENCRYPTED PRIVATE KEY-----
输入该命令如果提示输入密码直接回车即可。
在实际开发过程中,公钥的生成是私钥没有经过PKCS8转换生成的。所以在私钥加密过程中,必须用未转换格式私钥,对应的公钥才能解密.
2. RSA加密解密(android)
1)首先要导入两个BASE64操作相关的类:
import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
这两个包从sun.misc.BASE64Decoder.jar中导入,网上可下载。
用到这个包是因为RSA加密后的密文自动进行了BASE64加密。
2)具体实现代码如下(为了方便测试,代码中的公钥私钥跟上面的不同):
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.EditText;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.StreamCorruptedException;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
public final class Utils {
public static final StringSOURCE="1234abcd"; // 要加密的原文
/* openssl生成的私钥 */
public static finalStringPRIVATE_KEY="MIICWwIBAAKBgQC0GU7gWV1iRj1WIxV4GwxRVobmNtiKke6ku21Jm99Mds2ZgpBO"+"\r"
+"ksrprPkgdrxnJSKUlgnkYC7rImLbfpYqXzlwscV6BCR8srAl0odk93qffLb4Q0kN"+"\r"
+"pNtpjUyoJuppWd7oiOHAe+w2Tjl95PIW4Dq5tBBCD3Su/YQy2wScMvLpqwIDAQAB"+"\r"
+"AoGAJFkzRS5kHZCFkpv0GlCDNOtcwJvzKkx3uMGnNgMCl2Em78OdMm6IC4+AnF+6"+"\r"
+"eKrTBuAdUP1kmspO33P2BMlBQzl0zqpSrhR/tZ3l4mKB0/3Qqn6wycQawgc4CcYI"+"\r"
+"qbQFPqSESPinRArqR581H941i4EbHgg/6CODb2hvbxxaLEkCQQDpUknAmLtFVnyZ"+"\r"
+"bZjUh122F4Jdo2yBQ+ADEQm8z5ivBA/gs8I7V0rx4uMYOd2v3VuEWz9i8Ue2JKN7"+"\r"
+"xKut5KMVAkEAxZqwO3ftzZ9zWR9dsWnZyraaMuxmQ+Jbzlvh9bMA4p2ikO+9eXWm"+"\r"
+"DJyKeXtBd1RB744CPbEDnXg9BZWIg3uJvwJAdHhiXqUfXsaEnmZqUzVbn0lvB2VM"+"\r"
+"Bd8nFQDNVpZexocFkgrJ26uAuuyipnZEZsTeKV0PcEm3nYH+pgsQFFc83QJAXRV5"+"\r"
+"Xwono20xURJNeH18ctmB2esyYVgIFzWBQ9SG3jmTkuLcRpL9HYPAV2mQdT3jsY0b"+"\r"
+"0SPJqCwz0qWWIRnY0QJATA7t4lUgc+0Wp9rPbcfB1qCr9mHVpvPcv59DX5nukk75"+"\r"
+"5DzQmErPJzsF6Kl7qITXJmDDFawE91nowIA0dCka2Q=="+"\r";
/* openssl生成的公钥 */
public static finalStringPUCLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0GU7gWV1iRj1WIxV4GwxRVobm"+"\r"
+"NtiKke6ku21Jm99Mds2ZgpBOksrprPkgdrxnJSKUlgnkYC7rImLbfpYqXzlwscV6"+"\r"
+"BCR8srAl0odk93qffLb4Q0kNpNtpjUyoJuppWd7oiOHAe+w2Tjl95PIW4Dq5tBBC"+"\r"
+"D3Su/YQy2wScMvLpqwIDAQAB"+"\r";
private static BASE64Encoderencoder;
private static BASE64Decoderdecoder;
public static BASE64EncodergetEncoder() {
if(encoder==null) {
return newBASE64Encoder();
}
returnencoder;
}
public staticBASE64DecodergetDecoder() {
if(decoder==null) {
return newBASE64Decoder();
}
returndecoder;
}
/**
* 从字符串中加载私钥
* 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。
* @paramprivateKeyStr
*@return
*@throwsException
*/
public staticPrivateKeyloadPrivateKeyFromString(String privateKeyStr)throwsException {
try{
byte[] buffer =getDecoder().decodeBuffer(privateKeyStr); // 解开私钥的base64
PKCS8EncodedKeySpec keySpec =newPKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA","BC");
RSAPrivateKey priKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
Log.e("hubin","loadPrivateKeyFromString-->priKey="+ priKey);
return priKey;
}catch(NoSuchAlgorithmException e) {
throw newException("无此算法");
}catch(InvalidKeySpecException e) {
Log.e("hubin","私钥非法 :" + e);
e.printStackTrace();
}catch(NullPointerException e) {
throw newException("私钥数据为空");
}
return null;
}
/**
* RSA私钥加密
* @paramdata明文字节数组
* @param privateKey私钥
* */
public static byte[]encryptDataByPrivateKey(byte[] data,PrivateKey privateKey) {
try{
Cipher cipher = Cipher.getInstance("RSA");
// 编码前设定编码方式及密钥
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
// 传入编码数据并返回编码结果
returncipher.doFinal(data);
}catch(Exception e) {
e.printStackTrace();
return null;
}
}
/*从字符串中加载公钥 */
public staticPublicKeyloadPublicKeyFromString(String publicKeyStr)throwsException {
try{
byte[] buffer =getDecoder().decodeBuffer(publicKeyStr); // 解开公钥的base4
KeyFactory keyFactory = KeyFactory.getInstance("RSA","BC");
X509EncodedKeySpec keySpec =newX509EncodedKeySpec(buffer);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
Log.e("hubin","loadPublicKeyFromString-->pubKey="+ pubKey);
return pubKey;
}catch(NoSuchAlgorithmException e) {
Log.e("hubin","NoSuchAlgorithmException="+ e);
}catch(InvalidKeySpecException e) {
Log.e("hubin","InvalidKeySpecException=="+ e);
}catch(NullPointerException e) {
Log.e("hubin","NullPointerException==="+ e);
}
return null;
}
/**
* 用公钥解密
*
* @paramencryptedData
* 经过encryptDataByPrivateKey()加密返回的byte数据
* @parampublicKey
* 公钥
* @return
*/
public static byte[]decryptDataByPublicKey(byte[] encryptedData,PublicKey publicKey) {
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,publicKey);
return cipher.doFinal(encryptedData);
}catch(Exception e) {
return null;
}
}
}
3)调用加密解密方法
try {
//私钥加密
byte[] rsaByte = LicenseUtil.encryptDataByPrivateKey(LicenseUtil.SOURCE.getBytes(),
LicenseUtil.loadPrivateKeyFromString(LicenseUtil.PRIVATE_KEY));
//公钥解密
byte[] rsaDByte = LicenseUtil.decryptDataByPublicKey(rsaByte,LicenseUtil.loadPublicKeyFromString(LicenseUtil.PUCLIC_KEY));
String str =newString(rsaDByte); // 生成解密后的明文字符串
Log.e("hubin","rsa decode str=" + str); //打印解密结果,1234abcd
} catch(Exception e) {
e.printStackTrace();
}