安全
RSA
- RSA是最常用非對稱加密算法。常用于消息簽名。它的加解密的密鑰是成對出現(xiàn)的价说。使用私鑰加密只能用對應的公鑰才能解密瞎疼。這樣防止了類似DES等對稱加密算法的密鑰傳輸?shù)膯栴}。其加密效率比DES慢撇眯。
- 詳細內容請查看:http://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
/**
* RSA算法加密解密例子
* 注意:RSA加密對明文的長度是有限制的,RSA加密明文最大長度117字節(jié),解密要求密文最大長度為128字節(jié)会涎,所以在加密和解密的過程中需要分塊進行。
*
*/
public class RSACoder extends TestCase {
/**
* 測試用私鑰加密再用公鑰解密
*
* @throws Exception
*/
public void test1() throws Exception {
byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
System.out.println("加密前的明文:" + new String(arr, "GBK"));
Map<String, Object> keyMap = this.initKey();
PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");
byte[] encryptData = this.encryptByPriKey(arr, priKey.getEncoded());
System.out.println("密文:" + Hex.encodeHexString(encryptData));
byte[] data = this.decryptByPubKey(encryptData, pubKey.getEncoded());
System.out.println("解密后的明文:" + new String(data, "GBK"));
}
/**
* 測試數(shù)字簽名與驗簽
*
* @throws Exception
*/
public void test2() throws Exception {
byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
System.out.println("簽名主體:" + new String(arr, "GBK"));
Map<String, Object> keyMap = this.initKey();
PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");
byte[] sign = this.sign(arr, priKey.getEncoded());
System.out.println("簽名:" + Hex.encodeHexString(sign));
boolean b = this.verify(arr, pubKey.getEncoded(), sign);
System.out.println(b ? "驗簽成功" : "驗簽失敗");
}
/**
* 測試直接對主體簽名與先對主體加摘要再簽名得到的簽名是不一樣的瑞凑。
*
* @throws Exception
*/
public void test3() throws Exception {
byte[] arr = this.readFileIntoByteArr(new File("D:/data.txt"));
System.out.println("簽名主體:" + new String(arr, "GBK"));
Map<String, Object> keyMap = this.initKey();
PrivateKey priKey = (PrivateKey) keyMap.get("PrivateKey");
PublicKey pubKey = (PublicKey) keyMap.get("PublicKey");
// 直接簽名
byte[] sign1 = this.sign(arr, priKey.getEncoded());
System.out.println("簽名:" + Hex.encodeHexString(sign1));
// 先得到MD5摘要再簽名
byte[] md5 = DigestUtils.md5(arr);
byte[] sign2 = this.sign(md5, priKey.getEncoded());
System.out.println("簽名:" + Hex.encodeHexString(sign2));
}
/**
* 生成密鑰對
*
* @return
* @throws NoSuchAlgorithmException
*/
public Map<String, Object> initKey() throws NoSuchAlgorithmException {
// 實例化密鑰對生成器
KeyPairGenerator gener = KeyPairGenerator.getInstance("RSA");
gener.initialize(1024);
KeyPair pair = gener.generateKeyPair();
PrivateKey priKey = pair.getPrivate();
PublicKey pubKey = pair.getPublic();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put("PrivateKey", priKey);
keyMap.put("PublicKey", pubKey);
System.out.println("私鑰:" + Hex.encodeHexString(priKey.getEncoded()));
System.out.println("公鑰:" + Hex.encodeHexString(pubKey.getEncoded()));
return keyMap;
}
/**
* 讀取文件內容到byte數(shù)組
*
* @param file
* @return
* @throws IOException
*/
public byte[] readFileIntoByteArr(File file) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
FileInputStream in = new FileInputStream(file);
byte[] tmpbuf = new byte[1024];
int count = 0;
while ((count = in.read(tmpbuf)) != -1) {
bout.write(tmpbuf, 0, count);
tmpbuf = new byte[1024];
}
in.close();
} catch (FileNotFoundException e) {
throw new FileNotFoundException("文件" + file.getPath() + "不存在");
} catch (IOException e) {
throw new IOException("讀取文件內容到BYTE數(shù)組中出現(xiàn)IO異常", e);
}
return bout.toByteArray();
}
/**
* 私鑰加密
*
* @param data
* @param priKeyByte
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] encryptByPriKey(byte[] data, byte[] priKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 獲取私鑰
KeySpec spec = new PKCS8EncodedKeySpec(priKeyByte);
// 生成私鑰
Key priKey = keyFactory.generatePrivate(spec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, priKey);
return cipher.doFinal(data);
}
/**
* 公鑰解密
*
* @param data
* @param pubKeyByte
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] decryptByPubKey(byte[] data, byte[] pubKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 獲取公鑰
KeySpec spec = new X509EncodedKeySpec(pubKeyByte);
// 生成公鑰
Key pubKey = keyFactory.generatePublic(spec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, pubKey);
return cipher.doFinal(data);
}
/**
* 使用MD5withRSA算法末秃,加簽
*
* @param data
* @param priKeyByte
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
*/
public byte[] sign(byte[] data, byte[] priKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 獲取私鑰
KeySpec spec = new PKCS8EncodedKeySpec(priKeyByte);
// 生成私鑰
PrivateKey priKey = keyFactory.generatePrivate(spec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(priKey);
signature.update(data);
return signature.sign();
}
/**
* 使用MD5withRSA算法,解簽
*
* @param data
* @param pubKeyByte
* @param sign
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws InvalidKeyException
* @throws SignatureException
*/
public boolean verify(byte[] data, byte[] pubKeyByte, byte[] sign) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
SignatureException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 獲取公鑰
KeySpec spec = new X509EncodedKeySpec(pubKeyByte);
// 生成公鑰
PublicKey pubKey = keyFactory.generatePublic(spec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(sign);
}
}