著名的密碼學(xué)者Ron Rivest曾經(jīng)說過:“密碼學(xué)是關(guān)于如何在敵人存在的環(huán)境中通訊”器仗。
的確,從嚴(yán)謹(jǐn)?shù)慕嵌葋碇v,不管是公網(wǎng)環(huán)境還是在企業(yè)內(nèi)網(wǎng)猿妈,我們設(shè)計(jì)系統(tǒng)的時(shí)候都需要充分考慮通訊安全。以下總結(jié)了一些常用的java密碼技術(shù)巍虫,供參考彭则。
1,單向散列函數(shù)
又稱單向Hash函數(shù)占遥、雜湊函數(shù)俯抖,就是把任意長的輸入消息串變化成固定長的輸出串且由輸出串難以得到輸入串的一種函數(shù)。這個(gè)輸出串稱為該消息的散列值瓦胎。一般用于產(chǎn)生消息摘要芬萍,密鑰加密等.
1)MD5
是RSA數(shù)據(jù)安全公司開發(fā)的一種單向散列算法尤揣,MD5被廣泛使用。MD5的強(qiáng)抗碰撞性目前已被破解柬祠。
代碼示例:
package com.huangzi.demo;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
public static byte[] eccrypt(String info) throws NoSuchAlgorithmException{
//獲取MD5的MessageDigest對象
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] srcBytes = info.getBytes();
md5.update(srcBytes);
byte[] resultBytes = md5.digest();
return resultBytes;
}
public static void main(String args[]) throws NoSuchAlgorithmException{
String msg = "皇子——常用java密碼技術(shù)";
byte[] resultBytes = MD5.eccrypt(msg);
System.out.println("密文:" + new String(resultBytes));
System.out.println("明文:" + msg);
}
}
2)SHA
分為SHA-1北戏,SHA-224,SHA-256漫蛔,SHA-384嗜愈。目前SHA-1的強(qiáng)抗碰撞性已被破解。
package com.huangzi.demo;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA {
public static byte[] eccrypt(String shaType,String info) throws NoSuchAlgorithmException{
MessageDigest md5 = MessageDigest.getInstance(shaType);
byte[] srcBytes = info.getBytes();
md5.update(srcBytes);
byte[] resultBytes = md5.digest();
return resultBytes;
}
/**
* @param args
* @throws NoSuchAlgorithmException
*/
public static void main(String[] args) throws NoSuchAlgorithmException {
String msg = "皇子講java密碼技術(shù)";
String[] shaTypes = new String[] { "SHA1", "SHA-256", "SHA-384", "SHA-512" };
for(String shaType : shaTypes) {
System.out.println(shaType);
byte[] resultBytes = SHA.eccrypt(shaType,msg);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(resultBytes));
System.out.println("========================");
}
}
}
2惩猫,對稱加密
一種加密與解密用的是相同的密鑰的加密方式芝硬。
1)DES
DES,全稱為“Data Encryption Standard”轧房,中文名為“數(shù)據(jù)加密標(biāo)準(zhǔn)”拌阴,是一種使用密鑰加密的塊算法。1977年被美國聯(lián)邦政府的國家標(biāo)準(zhǔn)局確定為聯(lián)邦資料處理標(biāo)準(zhǔn)(FIPS)奶镶,并授權(quán)在非密級政府通信中使用迟赃,隨后該算法在國際上廣泛流傳開來。
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class DES {
private KeyGenerator keygen;
private SecretKey deskey;
private Cipher cipher;
private byte[] cipherByte;
public DES() throws NoSuchAlgorithmException, NoSuchPaddingException{
keygen = KeyGenerator.getInstance("DES");
deskey = keygen.generateKey();
cipher = Cipher.getInstance("DES");
}
public byte[] Encrytor(String str) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] src = str.getBytes();
cipherByte = cipher.doFinal(src);
return cipherByte;
}
public byte[] Decryptor(byte[] buff) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.DECRYPT_MODE, deskey);
cipherByte = cipher.doFinal(buff);
return cipherByte;
}
public static void main(String[] args) throws Exception {
DES de1 = new DES();
String msg ="皇子講java密碼技術(shù)";
byte[] encontent = de1.Encrytor(msg);
byte[] decontent = de1.Decryptor(encontent);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(encontent));
System.out.println("解密:" + new String(decontent));
}
}
2)3DES
又稱Triple DES厂镇,是DES加密算法的一種模式纤壁,它使用3條56位的密鑰對3DES數(shù)據(jù)進(jìn)行三次加密。
package com.huangzi.demo;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class DESDESDES {
private KeyGenerator keygen;
private SecretKey deskey;
private Cipher c;
private byte[] cipherByte;
public DESDESDES() throws NoSuchAlgorithmException, NoSuchPaddingException {
keygen = KeyGenerator.getInstance("DESede");
deskey = keygen.generateKey();
c = Cipher.getInstance("DESede");
}
/**
* 加密
*
* @param str
* @return
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] Encrytor(String str) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
c.init(Cipher.ENCRYPT_MODE, deskey);
byte[] src = str.getBytes();
cipherByte = c.doFinal(src);
return cipherByte;
}
/**
* 解密
*
* @param buff
* @return
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] Decryptor(byte[] buff) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
c.init(Cipher.DECRYPT_MODE, deskey);
cipherByte = c.doFinal(buff);
return cipherByte;
}
/**
* @param args
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
*/
public static void main(String[] args) throws Exception {
DESDESDES des = new DESDESDES();
String msg ="皇子講java密碼技術(shù)";
byte[] encontent = des.Encrytor(msg);
byte[] decontent = des.Decryptor(encontent);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(encontent));
System.out.println("解密:" + new String(decontent));
}
}
3)AES
高級加密標(biāo)準(zhǔn)(英語:Advanced Encryption Standard捺信,縮寫:AES)酌媒,在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)迄靠。由美國國家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)發(fā)布于FIPS PUB 197秒咨,并在2002年5月26日成為有效的標(biāo)準(zhǔn)。是對稱密鑰加密中最流行的算法之一掌挚。
package com.huangzi.demo;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class AES {
private KeyGenerator keygen;
private SecretKey deskey;
private Cipher cipher;
private byte[] cipherByte;
public AES() throws NoSuchAlgorithmException, NoSuchPaddingException{
keygen = KeyGenerator.getInstance("AES");
deskey = keygen.generateKey();
cipher = Cipher.getInstance("AES");
}
/**
* 加密
* @param str
* @return
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] Encrytor(String str) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] src = str.getBytes();
cipherByte = cipher.doFinal(src);
return cipherByte;
}
/**
* 解密
* @param buff
* @return
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] Decryptor(byte[] buff) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.DECRYPT_MODE, deskey);
cipherByte = cipher.doFinal(buff);
return cipherByte;
}
/**
* @param args
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
*/
public static void main(String[] args) throws Exception {
AES aes = new AES();
String msg ="皇子講java密碼技術(shù)";
byte[] encontent = aes.Encrytor(msg);
byte[] decontent = aes.Decryptor(encontent);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(encontent));
System.out.println("解密:" + new String(decontent));
}
}
4)PBE
PBE算法(Password Based Encryption雨席,基于口令加密)是一種基于口令的加密算法,其特點(diǎn)是使用口令代替了密鑰吠式,而口令由用戶自己掌管陡厘,采用隨機(jī)數(shù)雜湊多重加密等方法保證數(shù)據(jù)的安全性。
PBE算法在加密過程中并不是直接使用口令來加密特占,而是加密的密鑰由口令生成糙置,這個(gè)功能由PBE算法中的KDF函數(shù)完成。KDF函數(shù)的實(shí)現(xiàn)過程為:將用戶輸入的口令首先通過“鹽”(salt)的擾亂產(chǎn)生準(zhǔn)密鑰是目,再將準(zhǔn)密鑰經(jīng)過散列函數(shù)多次迭代后生成最終加密密鑰罢低,密鑰生成后,PBE算法再選用對稱加密算法對數(shù)據(jù)進(jìn)行加密,可以選擇DES网持、3DES宜岛、RC5等對稱加密算法。
package com.huangzi.demo;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class PEB {
private static Cipher cipher;
private static SecretKey generateKey;
private static PBEParameterSpec pbeParameterSpec;
public static byte[] encode(String src) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException{
SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(8);
String password = "abc123";
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
generateKey = secretKeyFactory.generateSecret(pbeKeySpec);
pbeParameterSpec = new PBEParameterSpec(salt, 100);
cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, generateKey, pbeParameterSpec);
return cipher.doFinal(src.getBytes());
}
public static byte[] decode(byte[] src) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{
cipher.init(Cipher.DECRYPT_MODE, generateKey, pbeParameterSpec);
return cipher.doFinal(src);
}
public static void main(String[] args) throws Exception{
String msg ="皇子講java密碼技術(shù)";
byte[] encontent = PEB.encode(msg);
byte[] decontent = PEB.decode(encontent);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(encontent));
System.out.println("解密:" + new String(decontent));
}
}
3功舀,公鑰密碼
公鑰密碼又稱為非對稱密碼萍倡,擁有公鑰密碼的用戶分別擁有加密密鑰和解密密鑰。通過加密密鑰不能得到解密密鑰辟汰。并且加密密鑰是公開的列敲。
解密密鑰一開始就由接收者自己保管,可以解決密鑰配送的問題
1)RSA
1977年由羅納德·李維斯特(Ron Rivest)帖汞、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的戴而。1987年7月首次在美國公布,當(dāng)時(shí)他們?nèi)硕荚诼槭±砉W(xué)院工作實(shí)習(xí)翩蘸。RSA就是他們?nèi)诵帐祥_頭字母拼在一起組成的所意。
RSA是目前最有影響力和最常用的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數(shù)密碼攻擊催首,已被ISO推薦為公鑰數(shù)據(jù)加密標(biāo)準(zhǔn)扶踊。
今天只有短的RSA鑰匙才可能被強(qiáng)力方式解破。到2008年為止郎任,世界上還沒有任何可靠的攻擊RSA算法的方式秧耗。只要其鑰匙的長度足夠長,用RSA加密的信息實(shí)際上是不能被解破的舶治。
但在分布式計(jì)算和量子計(jì)算機(jī)理論日趨成熟的今天分井,RSA加密安全性受到了挑戰(zhàn)和質(zhì)疑。
package com.huangzi.demo;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
public class RSA {
public static byte[] encrypt(RSAPublicKey publicKey,byte[] srcBytes) throws Exception{
if(publicKey!=null){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] resultBytes = cipher.doFinal(srcBytes);
return resultBytes;
}
return null;
}
public static byte[] decrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws Exception{
if(privateKey!=null){
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] resultBytes = cipher.doFinal(srcBytes);
return resultBytes;
}
return null;
}
public static void main(String[] args) throws Exception {
String msg = "皇子講java密碼技術(shù)";
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
byte[] srcBytes = msg.getBytes();
byte[] resultBytes = RSA.encrypt(publicKey, srcBytes);
byte[] decBytes = RSA.decrypt(privateKey, resultBytes);
System.out.println("明文:" + msg);
System.out.println("密文:" + new String(resultBytes));
System.out.println("解密:" + new String(decBytes));
}
}
4霉猛,數(shù)字簽名
數(shù)字簽名(又稱公鑰數(shù)字簽名杂抽、電子簽章)是一種類似寫在紙上的普通的物理簽名,但是使用了公鑰加密領(lǐng)域的技術(shù)實(shí)現(xiàn)韩脏,用于鑒別數(shù)字信息的方法。一套數(shù)字簽名通常定義兩種互補(bǔ)的運(yùn)算铸磅,一個(gè)用于簽名赡矢,另一個(gè)用于驗(yàn)證。
數(shù)字簽名會(huì)使用公鑰和私鑰組成的密鑰對
私鑰加密相當(dāng)于生成簽名阅仔;用公鑰解密相當(dāng)于驗(yàn)證簽名
package com.huangzi.demo;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
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;
public class RSASign {
public static byte[] sign(PrivateKey rsaPrivateKey,String msg) throws Exception{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update(msg.getBytes());
return signature.sign();
}
public static boolean verify(PublicKey rsaPublicKey,String msg,byte[] signatureByte) throws Exception {
Signature signature = Signature.getInstance("MD5withRSA");
signature = Signature.getInstance("MD5withRSA");
signature.initVerify(rsaPublicKey);
signature.update(msg.getBytes());
return signature.verify(signatureByte);
}
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
PrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
String msg = "皇子講java密碼技術(shù)";
byte[] signature = RSASign.sign(rsaPrivateKey, msg);
System.out.println("消息明文:" + msg);
System.out.println("簽名:" + new String(signature));
boolean flag = RSASign.verify(rsaPublicKey, msg, signature);
System.out.println("驗(yàn)簽結(jié)果:" + flag);
}
}
作者:VIP.FCS 皇子
日期:2018.1.14
來贊賞一瓶可樂吹散?