RSA算法的Java实现及Base64的正确使用
遇到的问题:
今天参考他人代码实现了一下RSA算法。遇到一个问题,网上的RSA工具类中的核心方法大多是需要传入byte[]数组进行处理,而不能直接传入String进行处理,这里对byte[]的处理部分进行了完全的封装,使用户的传入参数完全String化。大大简化了工具类的使用。
这其中有必要对Base64的用法做一点提炼:
今天参考他人代码实现了一下RSA算法。遇到一个问题,网上的RSA工具类中的核心方法大多是需要传入byte[]数组进行处理,而不能直接传入String进行处理,这里对byte[]的处理部分进行了完全的封装,使用户的传入参数完全String化。大大简化了工具类的使用。
这其中关键是需要用到Base64对String和byte[]进行互转。
Base64的jar包下载地址:http://download.csdn.net/detail/ldld1717/9772776
核心代码:
package RSARSA; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; public class RSATest { // 数字签名,密钥算法 private static final String RSA_KEY_ALGORITHM = "RSA"; // 数字签名签名/验证算法 private static final String SIGNATURE_ALGORITHM = "MD5withRSA"; // RSA密钥长度 private static final int KEY_SIZE = 1024; private static final String PUBLIC_KEY = "publicKey"; private static final String PRIVATE_KEY = "privateKey"; /** * 初始化RSA密钥对 * @return RSA密钥对 * @throws Exception 抛出异常 */ private static Map<String, String> initKey() throws Exception { KeyPairGenerator keygen = KeyPairGenerator .getInstance(RSA_KEY_ALGORITHM); SecureRandom secrand = new SecureRandom(); secrand.setSeed("hahaha".getBytes());// 初始化随机产生器 keygen.initialize(KEY_SIZE, secrand); // 初始化密钥生成器 KeyPair keys = keygen.genKeyPair(); String pub_key = Base64.encodeBase64String(keys.getPublic().getEncoded()); String pri_key = Base64.encodeBase64String(keys.getPrivate().getEncoded()); Map<String, String> keyMap = new HashMap<String, String>(); keyMap.put(PUBLIC_KEY, pub_key); keyMap.put(PRIVATE_KEY, pri_key); System.out.println("公钥:" + pub_key); System.out.println("私钥:" + pri_key); return keyMap; } /** * 得到公钥 * @param keyMap RSA密钥对 * @return 公钥 * @throws Exception 抛出异常 */ public static String getPublicKey(Map<String, String> keyMap) throws Exception{ return keyMap.get(PUBLIC_KEY); } /** * 得到私钥 * @param keyMap RSA密钥对 * @return 私钥 * @throws Exception 抛出异常 */ public static String getPrivateKey(Map<String, String> keyMap) throws Exception{ return keyMap.get(PRIVATE_KEY); } /** * 数字签名 * @param data 待签名数据 * @param pri_key 私钥 * @return 签名 * @throws Exception 抛出异常 */ public static String sign(byte[] data, String pri_key) throws Exception { // 取得私钥 byte[] pri_key_bytes = Base64.decodeBase64(pri_key); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key_bytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); // 生成私钥 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 实例化Signature Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); // 初始化Signature signature.initSign(priKey); // 更新 signature.update(data); return Base64.encodeBase64String(signature.sign()); } /** * RSA校验数字签名 * @param data 数据 * @param sign 签名 * @param pub_key 公钥 * @return 校验结果,成功为true,失败为false * @throws Exception 抛出异常 */ public boolean verify(byte[] data, byte[] sign, String pub_key) throws Exception { // 转换公钥材料 // 实例化密钥工厂 byte[] pub_key_bytes = Base64.decodeBase64(pub_key); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); // 初始化公钥 // 密钥材料转换 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key_bytes); // 产生公钥 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); // 实例化Signature Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); // 初始化Signature signature.initVerify(pubKey); // 更新 signature.update(data); // 验证 return signature.verify(sign); } /** * 公钥加密 * @param data 待加密数据 * @param pub_key 公钥 * @return 密文 * @throws Exception 抛出异常 */ private static byte[] encryptByPubKey(byte[] data, byte[] pub_key) throws Exception { // 取得公钥 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 公钥加密 * @param data 待加密数据 * @param pub_key 公钥 * @return 密文 * @throws Exception 抛出异常 */ public static String encryptByPubKey(String data, String pub_key) throws Exception { // 私匙加密 byte[] pub_key_bytes = Base64.decodeBase64(pub_key); byte[] enSign = encryptByPubKey(data.getBytes(), pub_key_bytes); return Base64.encodeBase64String(enSign); } /** * 私钥加密 * @param data 待加密数据 * @param pri_key 私钥 * @return 密文 * @throws Exception 抛出异常 */ private static byte[] encryptByPriKey(byte[] data, byte[] pri_key) throws Exception { // 取得私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 对数据加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 私钥加密 * @param data 待加密数据 * @param pri_key 私钥 * @return 密文 * @throws Exception 抛出异常 */ public static String encryptByPriKey(String data, String pri_key) throws Exception { // 私匙加密 byte[] pri_key_bytes = Base64.decodeBase64(pri_key); byte[] enSign = encryptByPriKey(data.getBytes(), pri_key_bytes); return Base64.encodeBase64String(enSign); } /** * 公钥解密 * @param data 待解密数据 * @param pub_key 公钥 * @return 明文 * @throws Exception 抛出异常 */ private static byte[] decryptByPubKey(byte[] data, byte[] pub_key) throws Exception { // 取得公钥 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pub_key); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 公钥解密 * @param data 待解密数据 * @param pub_key 公钥 * @return 明文 * @throws Exception 抛出异常 */ public static String decryptByPubKey(String data, String pub_key) throws Exception { // 公匙解密 byte[] pub_key_bytes = Base64.decodeBase64(pub_key); byte[] design = decryptByPubKey(Base64.decodeBase64(data), pub_key_bytes); return new String(design); } /** * 私钥解密 * @param data 待解密数据 * @param pri_key 私钥 * @return 明文 * @throws Exception 抛出异常 */ private static byte[] decryptByPriKey(byte[] data, byte[] pri_key) throws Exception { // 取得私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pri_key); KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 私钥解密 * @param data 待解密数据 * @param pri_key 私钥 * @return 明文 * @throws Exception 抛出异常 */ public static String decryptByPriKey(String data, String pri_key) throws Exception { // 私匙解密 byte[] pri_key_bytes = Base64.decodeBase64(pri_key); byte[] design = decryptByPriKey(Base64.decodeBase64(data), pri_key_bytes); return new String(design); } /** * @param args */ @SuppressWarnings("static-access") public static void main(String[] args) throws Exception { RSATest das = new RSATest(); String datastr = "天街小雨润如酥,草色遥看近却无。最是一年春好处,绝胜烟柳满皇都。"; System.out.println("待加密数据: " + datastr); //获取密钥对 Map<String, String> keyMap = new HashMap<String, String>(); keyMap = das.initKey(); String pub_key = (String) keyMap.get(PUBLIC_KEY); String pri_key = (String) keyMap.get(PRIVATE_KEY); // 公匙加密 String pubKeyStr = RSATest.encryptByPubKey(datastr, pub_key); System.out.println("公匙加密结果: " + pubKeyStr); // 私匙解密 String priKeyStr = RSATest.decryptByPriKey(pubKeyStr, pri_key); System.out.println("私匙解密结果: " + priKeyStr); //换行 System.out.println(); // 数字签名 String str1 = "汉兵已略地"; String str2 = "四面楚歌声"; System.out.println("正确的签名:" + str1 + " 错误的签名:" + str2); String sign = RSATest.sign(str1.getBytes(), pri_key); System.out.println("数字签名: " + sign); boolean vflag1 = das.verify(str1.getBytes(), Base64.decodeBase64(sign), pub_key); System.out.println("数字签名验证结果1: " + vflag1); boolean vflag2 = das.verify(str2.getBytes(), Base64.decodeBase64(sign), pub_key); System.out.println("数字签名验证结果2: " + vflag2); } }
这其中有必要对Base64的用法做一点提炼:
1.byte[]转为String用到Base64.encodeBase64String(传待转的byte数组)方法;
2.String转byte[]用到Base64.decodeBase64(传待转的字符串)方法;
3.以上两步若实现byte[]--->-String-->byte[],则byte[]不变,也不会有乱码,所以Base64还是非常好用的。
实验结果:
实验结果完全符合预期。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。