上网研究了一下RSA加密解密和作为数字签名的用法,整理了一下,写了一个类,总结了用法。
用到了commons-codec-1.6.jar的Base64类
package tj.rsa_pkcs;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.CharEncoding;
import org.apache.commons.codec.binary.Base64;
public class T1 {
static final String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANQCoC6334MPhQWnfTDUZ7N1P2clRTfoDp/uMCClSMY1Ptf57nMYa87QbzSui61/9xtNKr1MJ2vCff2La5Dp0vGcWyTOKebva1QgPs/G8Vm7wG2QtB4vlkEj0Mfga2IEbTrz8Drk4wSO8gKNjI9E8EnoBKKcUTAjJsgDiPoUP6YRAgMBAAECgYEAlI2WccXTLoFUYwbd+LYMR7mzCHIcEzVd8gAy5t0JpiCu/SSaSTlmaQ6xrUdUheixXAbxGJzgzmgEYgEsCOleLTkg5+cUp0MJ7SfoEdrz/dtjp9+M2CQMpCUVRVoHlJLbRB3AEwo+PEnefu/gkx6k2E/sEuzDbiopQpO1ZcWsnvECQQDuax56efeAiijve2cmtDbkICuEX6db1we/+cwUawp0E5grADI7VGA//z2RUl/wBn+okeVZdNrx2ls5WvXhS7UNAkEA46T4m3+lAA6nAIBHRCksgFPWWP2Per22WyblUr6Sp3sYjtBUx10znQexV9t2sBP4Gg++NbUv3yKIKBZWa9X8FQJBAKZ8Xrgf21kDITq57Xn1di8u17SEJxXWvi6sfHn1lUMhO60rYehULzIBRjjoUN4Ha7WGy6UAGLOySuluPyyn9TECQGzW5V5DazpZxxMAQhKetP4uF1+46669ocB3GlGzeB7HRfiSNtaTAyhjEzF0ZozNH2QmfsTi+h5vPjYcZ/lq9/kCQQCwDYpT2Pz2bmmESyJIjjgLLvyoa1irG0sNvFtNczayj25IzTSTQttBdByi5zteoO2sDvHOAxaE/pdL9HM64bNE";
static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUAqAut9+DD4UFp30w1GezdT9nJUU36A6f7jAgpUjGNT7X+e5zGGvO0G80routf/cbTSq9TCdrwn39i2uQ6dLxnFskzinm72tUID7PxvFZu8BtkLQeL5ZBI9DH4GtiBG068/A65OMEjvICjYyPRPBJ6ASinFEwIybIA4j6FD+mEQIDAQAB";
/**
* 加密算法RSA
*/
static final String algorithm = "RSA";
/**
* 初始化,生成私钥和公钥
*
* @param
* @return void
* @author Administrator
* @throws NoSuchAlgorithmException
* @Create 2015年4月16日 下午3:45:07
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static void initKey() throws NoSuchAlgorithmException{
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
kpg.initialize(1024);
kpg.genKeyPair().getPrivate();
KeyPair keyPair = kpg.generateKeyPair();
//公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
System.out.println("--------------------------------public key --------------------------------");
System.out.println(Base64.encodeBase64String(publicKey.getEncoded()));
//私钥
System.out.println("--------------------------------private key --------------------------------");
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
System.out.println(Base64.encodeBase64String(privateKey.getEncoded()));
}
/**
* 用私钥加密
*
* @param @param input
* @param @param privateKey
* @param @return
* @param @throws NoSuchAlgorithmException
* @param @throws Exception
* @return String
* @author Administrator
* @Create 2015年4月16日 下午4:26:04
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static byte[] encryptByPrivateKey(byte[] input,String privateKey) throws NoSuchAlgorithmException, Exception{
//解密私钥,生成PKCS8EncodedKeySpec对象
//PKCS8EncodedKeySpec的JDK描述:此类表示按照 ASN.1 类型 PrivateKeyInfo 进行编码的专用密钥的 ASN.1 编码
//PKCS8EncodedKeySpec用于私钥
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
//生成RSA 加密工厂类
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
//生成加密的Key
Key key = keyFactory.generatePrivate(keySpec);
//创建Cipher对象(此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心。)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//初始化Cipher,设置模式为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);
//对数据进行加密
byte[] resultBytes = cipher.doFinal(input);
return resultBytes;
}
/**
* 用公钥解密
*
* @param @param fromContent
* @param @param publicKey
* @param @param charset
* @param @return
* @param @throws Exception
* @return String
* @author Administrator
* @Create 2015年4月16日 下午3:44:02
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static byte[] decryptByPublicKey(byte[] data,String publicKey) throws Exception{
//解密公钥,生成X509EncodedKeySpec对象
//X509EncodedKeySpec的JDK描述:此类表示根据 ASN.1 类型 SubjectPublicKeyInfo 进行编码的公用密钥的 ASN.1 编码
//X509EncodedKeySpec用于公钥
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
//生成RSA 加密工厂类
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
//生成加密的Key
Key key = keyFactory.generatePublic(keySpec);
//创建Cipher对象(此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心。)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//初始化Cipher,设置模式为解密模式
cipher.init(Cipher.DECRYPT_MODE, key);
//rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
InputStream is = new ByteArrayInputStream(data);
ByteArrayOutputStream write = new ByteArrayOutputStream();
byte[] buff = new byte[128];
int buffl ;
while((buffl=is.read(buff))!=-1){
byte[] block = null;
if(buffl==buff.length){
block = buff;
}else {
block = new byte[buffl];
for (int i = 0; i < buffl; i++) {
block[i] = buff[i];
}
}
write.write(cipher.doFinal(block));
}
return write.toByteArray();
}
/**
* 用公钥加密
*
* @param @param input
* @param @param publicKey
* @param @return
* @param @throws Exception
* @return byte[]
* @author Administrator
* @Create 2015年4月16日 下午4:44:12
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static byte[] encryptByPublicKey(byte[] input,String publicKey) throws Exception{
//解密公钥,生成KeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
//生成RSA 加密工厂类
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
//生成加密的Key
Key key = keyFactory.generatePublic(keySpec);
//创建Cipher对象(此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心。)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//初始化Cipher,设置模式为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key);
//对数据进行加密
byte[] resultBytes = cipher.doFinal(input);
return resultBytes;
}
/**
* 用私钥解密
*
* @param @param data
* @param @param privateKey
* @param @return
* @param @throws Exception
* @return byte[]
* @author Administrator
* @Create 2015年4月16日 下午4:44:58
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static byte[] decryptByPrivateKey(byte[] data,String privateKey) throws Exception{
//解密公钥,生成KeySpec对象
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
//生成RSA 加密工厂类
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
//生成加密的Key
Key key = keyFactory.generatePrivate(keySpec);
//创建Cipher对象(此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心。)
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//初始化Cipher,设置模式为解密模式
cipher.init(Cipher.DECRYPT_MODE, key);
//rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
InputStream is = new ByteArrayInputStream(data);
ByteArrayOutputStream write = new ByteArrayOutputStream();
byte[] buff = new byte[128];
int buffl ;
while((buffl=is.read(buff))!=-1){
byte[] block = null;
if(buffl==buff.length){
block = buff;
}else {
block = new byte[buffl];
for (int i = 0; i < buffl; i++) {
block[i] = buff[i];
}
}
write.write(cipher.doFinal(block));
}
return write.toByteArray();
}
/**
* 签名算法 也可以是MD5withRSA或者其他
*/
static final String SIGN_ALGORITHMS = "SHA1WithRSA";
/**
* 对数据进行签名
*
* @param @param content
* @param @param privateKey
* @param @param charset
* @param @return
* @return String
* @author Administrator
* @throws Exception
* @Create 2015年4月16日 下午4:49:24
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static String sign(String content,String privateKey,String charset) throws Exception{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PrivateKey key = keyFactory.generatePrivate(keySpec);
//生成签名对象
Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
//通过私钥初始化
signature.initSign(key);
//写入要签名的数据
signature.update(content.getBytes(charset));
//获得签名后的数据
byte[] signData = signature.sign();
//进行base64编码后返回
return Base64.encodeBase64String(signData);
}
/**
* 校验签名数据是否正确
*
* @param @param content
* @param @param signStr
* @param @param publicKey
* @param @param charset
* @param @return
* @param @throws Exception
* @return boolean
* @author Administrator
* @Create 2015年4月16日 下午5:06:42
* @Modify {修改人1} {修改时间1} {修改目的1}
*/
public static boolean verify(String content,String signStr,String publicKey,String charset) throws Exception{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
//初始化校验
signature.initVerify(key);
//更新数据到签名对象
signature.update(content.getBytes(charset));
//校验 因为这里的signStr之前签名后是base加密的,所以这里要先base64解密
boolean isVerify = signature.verify(Base64.decodeBase64(signStr));
return isVerify;
}
public static void main(String[] args) throws Exception {
// 初始化key
// initKey();
String content = "123";
System.out.println("------------------下面是公钥加密和私钥解密------------------");
//对数据进行加密
byte[] encryptedData = encryptByPublicKey(content.getBytes(), publicKey);
String encryptedStr = Base64.encodeBase64String(encryptedData);
System.out.println("加密后的字符串:"+encryptedStr);
//解密
byte[] s = decryptByPrivateKey(Base64.decodeBase64(encryptedStr), privateKey);
// byte[] s = decryptByPrivateKey(encryptedData, privateKey);//直接使用加密后的byte数组就行
System.out.println("解密后:"+new String(s));
System.out.println("------------------下面是私钥加密和公钥解密------------------");
//对数据进行加密
byte[] encryptedData2 = encryptByPrivateKey(content.getBytes(), privateKey);
//解密
byte[] s2 = decryptByPublicKey(encryptedData2, publicKey);//直接使用加密后的byte数组就行
System.out.println("解密后:"+new String(s2));
System.out.println("------------------下面是签名和签名验证------------------");
String signStr = sign(content, privateKey, CharEncoding.UTF_8);
System.out.println("签名数据:"+signStr);
System.out.println("签名验证结果:"+verify("223", signStr, publicKey, CharEncoding.UTF_8));
System.out.println("签名验证结果:"+verify("123", signStr, publicKey, CharEncoding.UTF_8));
}
}