常用的Java加密技術和核心代碼系列:
Base64以及關於Base64遇到的坑 https://blog.csdn.net/haponchang/article/details/106094115
消息摘要算法 https://blog.csdn.net/haponchang/article/details/106096542
對稱加密(DES、3DES、AES、PBE) https://blog.csdn.net/haponchang/article/details/106096766
非對稱加密(RSA、DH) https://blog.csdn.net/haponchang/article/details/106097998
數字簽名證書 https://blog.csdn.net/haponchang/article/details/106098779
概念
非對稱加密算法需要兩個密鑰來進行加密和解密,分別是公鑰和私鑰。需要注意的一點,這個公鑰和私鑰必須是一對的,如果用公鑰對數據進行加密,那麼只有使用對應的私鑰才能解密,反之亦然。由於加密和解密使用的是兩個不同的密鑰,因此,這種算法叫做非對稱加密算法。
常見對稱加密算法有RSA、DH。
RSA
RSA 算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作爲加密密鑰。
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
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.Cipher;
import org.apache.commons.codec.binary.Hex;
public class RSAStrategy {
private RSAPublicKey rsaPublicKey;
private RSAPrivateKey rsaPrivateKey;
public String encode(String src) {
try {
//初始化密鑰
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance ("RSA");
keyPairGenerator.initialize (512);
KeyPair keyPair = keyPairGenerator.generateKeyPair ( );
rsaPublicKey = (RSAPublicKey) keyPair.getPublic ( );
rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate ( );
//私鑰加密 公鑰解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec
= new PKCS8EncodedKeySpec (rsaPrivateKey.getEncoded ( ));
KeyFactory keyFactory = KeyFactory.getInstance ("RSA");
PrivateKey privateKey = keyFactory.generatePrivate (pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance ("RSA");
cipher.init (Cipher.ENCRYPT_MODE, privateKey);
byte[] resultBytes = cipher.doFinal (src.getBytes ( ));
//私鑰解密 公鑰加密
// X509EncodedKeySpec x509EncodedKeySpec =
// new X509EncodedKeySpec(rsaPublicKey.getEncoded());
// KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// Cipher cipher = Cipher.getInstance("RSA");
// cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// byte[] resultBytes = cipher.doFinal(src.getBytes());
return Hex.encodeHexString (resultBytes);
} catch (Exception e) {
e.printStackTrace ( );
}
return null;
}
public String decode(String src) {
try {
//私鑰加密 公鑰解密
X509EncodedKeySpec x509EncodedKeySpec =
new X509EncodedKeySpec (rsaPublicKey.getEncoded ( ));
KeyFactory keyFactory = KeyFactory.getInstance ("RSA");
PublicKey publicKey = keyFactory.generatePublic (x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance ("RSA");
cipher.init (Cipher.DECRYPT_MODE, publicKey);
byte[] resultBytes = cipher.doFinal (Hex.decodeHex (src.toCharArray ( )));
//私鑰解密 公鑰加密
// PKCS8EncodedKeySpec pkcs8EncodedKeySpec
// = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
// KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// Cipher cipher = Cipher.getInstance("RSA");
// cipher.init(Cipher.DECRYPT_MODE, privateKey);
// byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));
return new String (resultBytes);
} catch (Exception e) {
e.printStackTrace ( );
}
return null;
}
}
DH
DH,全稱爲“Diffie-Hellman”,他是一種確保共享KEY安全穿越不安全網絡的方法,也就是常說的密鑰一致協議。由公開密鑰密碼體制的奠基人Diffie和Hellman所提出的一種思想。簡單的說就是允許兩名用戶在公開媒體上交換信息以生成“一致”的、可以共享的密鑰。也就是由甲方產出一對密鑰(公鑰、私鑰),乙方依照甲方公鑰產生乙方密鑰對(公鑰、私鑰)。
以此爲基線,作爲數據傳輸保密基礎,同時雙方使用同一種對稱加密算法構建本地密鑰(SecretKey)對數據加密。這樣,在互通了本地密鑰(SecretKey)算法後,甲乙雙方公開自己的公鑰,使用對方的公鑰和剛纔產生的私鑰加密數據,同時可以使用對方的公鑰和自己的私鑰對數據解密。不單單是甲乙雙方兩方,可以擴展爲多方共享數據通訊,這樣就完成了網絡交互數據的安全通訊!
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Hex;
public class DHStrategy {
private Cipher cipher;
private SecretKey receiverSecretKey;
public String encode(String src) {
try {
//初始化發送方密鑰
KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance ("DH");
senderKeyPairGenerator.initialize (512);
KeyPair senderkeyPair = senderKeyPairGenerator.generateKeyPair ( );
PrivateKey senderPrivateKey = senderkeyPair.getPrivate ( );
byte[] senderPublicKeyBytes = senderkeyPair.getPublic ( ).getEncoded ( );//發送方的公鑰
//初始化接收方密鑰,用發送方的公鑰
KeyFactory receiverKeyFactory = KeyFactory.getInstance ("DH");
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec (senderPublicKeyBytes);
PublicKey receiverPublicKey = receiverKeyFactory.generatePublic (x509EncodedKeySpec);
DHParameterSpec dhParameterSpec =
((DHPublicKey) receiverPublicKey).getParams ( );
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance ("DH");
receiverKeyPairGenerator.initialize (dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair ( );
PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate ( );
byte[] receiverPublicKeyBytes = receiverKeyPair.getPublic ( ).getEncoded ( );
KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance ("DH");
receiverKeyAgreement.init (receiverPrivateKey);
receiverKeyAgreement.doPhase (receiverPublicKey, true);
receiverSecretKey = receiverKeyAgreement.generateSecret ("DES");
//發送方拿到接收方的public key就可以做加密了
KeyFactory senderKeyFactory = KeyFactory.getInstance ("DH");
x509EncodedKeySpec = new X509EncodedKeySpec (receiverPublicKeyBytes);
PublicKey senderPublicKey = senderKeyFactory.generatePublic (x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance ("DH");
senderKeyAgreement.init (senderPrivateKey);
senderKeyAgreement.doPhase (senderPublicKey, true);
SecretKey senderSecretKey = senderKeyAgreement.generateSecret ("DES");
if (Objects.equals (receiverSecretKey, senderSecretKey)) {
cipher = Cipher.getInstance ("DES");
cipher.init (Cipher.ENCRYPT_MODE, senderSecretKey);
byte[] result = cipher.doFinal (src.getBytes ( ));
return Hex.encodeHexString (result);
}
} catch (Exception e) {
e.printStackTrace ( );
}
return null;
}
public String decode(String src) {
try {
cipher.init (Cipher.DECRYPT_MODE, receiverSecretKey);
byte[] result = Hex.decodeHex (src.toCharArray ( ));
return new String (cipher.doFinal (result));
} catch (Exception e) {
e.printStackTrace ( );
}
return null;
}
}