java各種加密方法實現
阿新 • • 發佈:2019-02-08
一般來講,在java上實現加密解密演算法,有3種方式。
- 自行實現演算法、
- 使用java自帶的crypto軟體包
- 使用第三方庫
本文講述一下第二種使用方法。我最開始也是找了很多這方面的資料,但是總感覺還是缺乏一些細節。現將我的一些心得與大家分享。
本文給出的例子基於下面的blog中所給出的例子。
blog.csdn.net/wildandfly/article/details/21521857
首先,現代密碼學演算法大致可以分為3個大塊。分別是對稱加密symmetric,非對稱加密asymmetric,訊息摘要hash。
本文實現了下列的幾種演算法,其中每個package中的演算法都非常類似。
不羅嗦,直接上程式碼
1對稱加密
以AES為例。注意其中keygenerator函式,其中keygenerator.getInstance()函式需要輸入對應的密碼方法,從而生成對應長度的key。
這裡,我查了下doc。可以傳入的引數如下圖。
package com.zhicheng.cryptogram;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSONObject;
/**
* 根據指定的16位aes_key,對id進行加解密
* @author wb-zcf274530
*
*/
public class SymmetricEncryption {
//金鑰生成支援16位字元
private static final String aes_key = "assistant7654321";
public static String encrypt(long id) {
byte[] key = Base64.decodeBase64(aes_key);
byte[] input = String.valueOf(id).getBytes();
byte[] encryptBytes = Cryptos.aesEncrypt(input, key);
return Base64.encodeBase64URLSafeString(encryptBytes);
}
public static Long decrypt(String securityId) {
byte[] key = Base64.decodeBase64(aes_key);
String value = Cryptos.aesDecrypt(Base64.decodeBase64(securityId), key);
return Long.parseLong(value);
}
static class Cryptos{
private static final String AES = "AES";
public static byte[] aesEncrypt(byte[] input,byte[] key) {
// ENCRYPT_MODE表示加密模式
return aes(input,key,Cipher.ENCRYPT_MODE);
}
public static String aesDecrypt(byte[] input,byte[] key) {
// DECRYPT_MODE表示解密模式
byte[] decypt = aes(input,key,Cipher.DECRYPT_MODE);
return new String(decypt);
}
private static byte[] aes(byte[] input,byte[] key,int mode) {
try {
//根據指定關鍵字進行獲取加密金鑰
SecretKey secretKey = new SecretKeySpec(key, AES);
//例項化支援AES演算法的金鑰生成器(演算法名稱命名需按規定,否則丟擲異常)
Cipher cipher = Cipher.getInstance(AES);
//根據金鑰,對Cipher物件進行初始化
cipher.init(mode, secretKey);
return cipher.doFinal(input);
}catch(Exception e) {
throw unchecked(e);
}
}
/**
* 生成金鑰
* @return
*/
public static String generateKey() {
KeyGenerator keygen = null;
try {
keygen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
}
//SecretKey 負責儲存對稱金鑰
SecretKey deskey = keygen.generateKey();
return Base64.encodeBase64String(deskey.getEncoded());
}
/**
* 將CheckedException轉換為UncheckedException.
*/
private static RuntimeException unchecked(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new RuntimeException(e);
}
}
public static void main(String[] args) throws NoSuchAlgorithmException {
/*String result = encrypt(1989L);
System.out.println(result);;
System.out.println("the encrypt:"+decrypt(result));*/
KeyGenerator keygen = KeyGenerator.getInstance("AES");
//SecretKey 負責儲存對稱金鑰
SecretKey deskey = keygen.generateKey();
System.out.println(Base64.encodeBase64String(deskey.getEncoded()));
}
}
}
2非對稱加密
以rsa為例,由於公鑰加密體系需要2個key值,故產生key值的函式也發生了改變。
keypairgenerator.getInstance()函式同樣需要傳入加密的方法,產生對應的key值。
這裡,我也查了下doc,如下。
package com.zhicheng.cryptogram;
import java.security.InvalidKeyException;
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.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
/**
* 非對稱性加密(公私鑰加密)
* 1、每次生成的公私鑰對都是不同的,所以要求對其進行儲存
* @author wb-zcf274530
*
*/
public class AsymmetricEncryption {
private static final String RSA = "RSA";
/**
* 加密
*
* @param publicKey
* @param srcBytes
* @return
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] encrypt(String publicKey, byte[] srcBytes) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
if (publicKey != null) {
PublicKey key = getPublicKey(publicKey);
return rsa(key,srcBytes,Cipher.ENCRYPT_MODE);
}
}catch(Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 獲取公鑰
* @param filename
* @return
* @throws Exception
*/
private static PublicKey getPublicKey(String publicKey) throws Exception {
byte[] publicKeys = Base64.decodeBase64(publicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeys);
KeyFactory kf = KeyFactory.getInstance(RSA);
return kf.generatePublic(spec);
}
/**
* 獲取私鑰
* @param filename
* @return
* @throws Exception
*/
private static PrivateKey getPrivateKey(String privateKey)throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec spec =new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance(RSA);
return kf.generatePrivate(spec);
}
/**
* 解密
*
* @param privateKey
* @param srcBytes
* @return
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] decrypt(String privateKey, byte[] srcBytes) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
if (privateKey != null) {
PrivateKey key = getPrivateKey(privateKey);
// 根據公鑰,對Cipher物件進行初始化
return rsa(key,srcBytes,Cipher.DECRYPT_MODE);
}
}catch(Exception e) {
e.printStackTrace();
}
return null;
}
public byte[] rsa(Key key,byte[] input,int mode) throws IllegalBlockSizeException,
BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException {
Cipher cipher = Cipher.getInstance(RSA);
// 根據公鑰,對Cipher物件進行初始化
cipher.init(mode, key);
byte[] resultBytes = cipher.doFinal(input);
return resultBytes;
}
/**
* @param args
* @throws NoSuchAlgorithmException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
*/
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException {
AsymmetricEncryption rsa = new AsymmetricEncryption();
String msg = "www.suning.com/index.jsp";
// KeyPairGenerator類用於生成公鑰和私鑰對,基於RSA演算法生成物件
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
// 初始化金鑰對生成器,金鑰大小為1024位
keyPairGen.initialize(1024);
// 生成一個金鑰對,儲存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私鑰
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公鑰
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 用公鑰加密
byte[] srcBytes = msg.getBytes();
byte[] resultBytes = rsa.encrypt(Base64.encodeBase64String(publicKey.getEncoded()), srcBytes);
System.out.println(Base64.encodeBase64String(publicKey.getEncoded()));
// 用私鑰解密
byte[] decBytes = rsa.decrypt(Base64.encodeBase64String(privateKey.getEncoded()), resultBytes);
System.out.println(Base64.encodeBase64String(privateKey.getEncoded()));
System.out.println("明文是:" + msg);
System.out.println("加密後是:" + new String(resultBytes));
System.out.println("解密後是:" + new String(decBytes));
}
}
3hash函式
這個由於我沒有用到,暫時就不寫了,以後再補上。
注意:
在1、2中除了keygenerator需要傳遞密碼的方法,cipher在初始化時也需要指定其引數。如下所示。