對稱加密算法是應用較早的加密算法,技術成熟。在對稱加密算法中,數據發信方將明文(原始數據)和加密密鑰一塊兒通過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則須要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密算法中,使用的密鑰只有一個,發收信雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰。java
對稱加密算法的優勢是:算法公開、計算量小、加密速度快、加密效率高。缺點是:首先,交易雙方都使用一樣鑰匙,安全性得不到保證。其次,每對用戶每次使用對稱加密算法時,都須要使用其餘人不知道的唯一鑰匙,這會使得發收信雙方所擁有的鑰匙數量呈幾何級數增加,密鑰管理成爲用戶的負擔。對稱加密算法在分佈式網絡系統上使用較爲困難,主要是由於密鑰管理困難,使用成本較高。算法
DES算法是最流行的對稱加密算法,全稱是Data Encryption Standard,即數據加密算法,它是IBM公司於1975年研究成功並公開發表的。DES算法的入口參數有三個:Key、Data、Mode。其中Key爲8個字節共64位,是DES算法的工做密鑰;Data也爲8個字節64位,是要被加密或被解密的數據;Mode爲DES的工做方式,有兩種:加密或解密。編程
能夠對數據進行三次DES算法,從而造成3DES算法。此算法至關因而對每一個數據塊應用三次DES加密算法。因爲計算機運算能力的加強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES便是設計用來提供一種相對簡單的方法,即經過增長DES的密鑰長度來避免相似的攻擊,而不是設計一種全新的塊密碼算法。對此算法的介紹,本文後面再也不贅述。數組
a.算法原理安全
DES算法把64位的明文輸入塊變爲64位的密文輸出塊,它所使用的密鑰也是64位,其算法主要分爲兩步:網絡
1.初始置換框架
其功能是把輸入的64位數據塊按位從新組合,並把輸出分爲L0、R0兩部分,每部分各長32位,其置換規則爲將輸入的第58位換到第一位,第50位換到第2位……依此類推,最後一位是原來的第7位。L0、R0則是換位輸出後的兩部分,L0是輸出的左32位,R0是右32位,例:設置換前的輸入值爲D1D2D3……D64,則通過初始置換後的結果爲:L0=D58D50……D8;R0=D57D49……D7。dom
2.逆置換編程語言
通過16次迭代運算後,獲得L1六、R16,將此做爲輸入,進行逆置換,逆置換正好是初始置換的逆運算,由此即獲得密文輸出。分佈式
b.DES算法在Java中的實現及運用
Java中爲安全框架提供類和接口。JDK 安全 API 是 Java 編程語言的核心 API,位於 java.security 包(及其子包),以及sun.securityAPI包(及其子包)中。設計用於幫助開發人員在程序中同時使用低級和高級安全功能。
應用實例:
private static int parse(char c) {
if (c >= 'a')
return (c - 'a' + 10) & 0x0f;
if (c >= 'A')
return (c - 'A' + 10) & 0x0f;
return (c - '0') & 0x0f;
}
// 從十六進制字符串到字節數組轉換
public static byte[] HexString2Bytes(String hexstr) {
byte[] b = new byte[hexstr.length() / 2];
int j = 0;
for (int i = 0; i < b.length; i++) {
char c0 = hexstr.charAt(j++);
char c1 = hexstr.charAt(j++);
b[i] = (byte) ((parse(c0) << 4) | parse(c1));
}
return b;
}
private static SecretKey keyGenerator(String keyStr) throws Exception {
byte input[] = HexString2Bytes(keyStr);
DESKeySpec desKey = new DESKeySpec(input);
// 建立一個密匙工廠,而後用它把DESKeySpec轉換成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
return securekey;
}
// 加密
public static String encrypt(String data, String key) throws Exception {
Key deskey = keyGenerator(key);
// 實例化Cipher對象,它用於完成實際的加密操做
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
SecureRandom random = new SecureRandom();
// 初始化Cipher對象,設置爲加密模式
cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
byte[] results = cipher.doFinal(data.getBytes());
// 執行加密操做。加密後的結果一般都會用Base64編碼進行傳輸
return Base64.encodeBase64String(results);
}
// 解密
public static String decrypt(String data, String key) throws Exception {
Key deskey = keyGenerator(key);
Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
// 初始化Cipher對象,設置爲解密模式
cipher.init(Cipher.DECRYPT_MODE, deskey);
// 執行解密操做
return new String(cipher.doFinal(Base64.decodeBase64(data)));
}
非對稱加密算法的核心源於數學問題,它存在公鑰和私鑰的概念,要完成加解密操做,須要兩個密鑰同時參與。
非對稱密碼體制的特色:算法強度複雜、安全性依賴於算法與密鑰可是因爲其算法複雜,而使得加密解密速度沒有對稱加密解密的速度快。對稱密碼體制中只有一種密鑰,而且是非公開的,若是要解密就得讓對方知道密鑰。因此保證其安全性就是保證密鑰的安全,而非對稱密鑰體制有兩種密鑰,其中一個是公開的,這樣就能夠不須要像對稱密碼那樣傳輸對方的密鑰了。這樣安全性就大了不少。
RSA加密算法是一種典型的非對稱加密算法,它基於大數的因式分解數學難題,它也是應用最普遍的非對稱加密算法,於1978年由美國麻省理工學院(MIT)的三位學着:Ron Rivest、Adi Shamir 和 Leonard Adleman 共同提出。
a.算法原理
RSA的原理較爲簡單。咱們假設有消息發送方A和消息接收方B,經過下面的幾個步驟,咱們就能夠完成消息的加密傳遞:
1)消息發送方A在本地構建密鑰對,公鑰和私鑰;
2)消息發送方A將產生的公鑰發送給消息接收方B;
3)B向A發送數據時,經過公鑰進行加密,A接收到數據後經過私鑰進行解密,完成一次通訊;
4)反之,A向B發送數據時,經過私鑰對數據進行加密,B接收到數據後經過公鑰進行解密。
因爲公鑰是消息發送方A暴露給消息接收方B的,因此這種方式也存在必定的安全隱患,若是公鑰在數據傳輸過程當中泄漏,則A經過私鑰加密的數據就可能被解密。
若是要創建更安全的加密消息傳遞模型,須要消息發送方和消息接收方各構建一套密鑰對,並分別將各自的公鑰暴露給對方,在進行消息傳遞時,A經過B的公鑰對數據加密,B接收到消息經過B的私鑰進行解密,反之,B經過A的公鑰進行加密,A接收到消息後經過A的私鑰進行解密。
固然,這種方式可能存在數據傳遞被模擬的隱患,咱們能夠經過數字簽名等技術進行安全性的進一步提高。因爲存在屢次的非對稱加解密,這種方式帶來的效率問題也更加嚴重。
DES算法在Java中的實現及運用:
// 用私鑰對信息生成數字簽名
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64編碼的私鑰
byte[] keyBytes = decryptBASE64(privateKey);
// 構造PKCS8EncodedKeySpec對象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 取私鑰匙對象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私鑰對信息生成數字簽名
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
// 校驗數字簽名
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
// 解密由base64編碼的公鑰
byte[] keyBytes = decryptBASE64(publicKey);
// 構造X509EncodedKeySpec對象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 取公鑰匙對象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(pubKey);
signature.update(data);
// 驗證簽名是否正常
return signature.verify(decryptBASE64(sign));
}
// 對私鑰解密
public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得私鑰
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 對數據解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
// 用公鑰解密
public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得公鑰
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 對數據解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
// 用公鑰加密
public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
// 對公鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得公鑰
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 對數據加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
// 用私鑰加密
public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得私鑰
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 對數據加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
// 取得私鑰
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get("RSAPrivateKey");
return encryptBASE64(key.getEncoded());
}
// 取得公鑰
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get("RSAPublicKey");
return encryptBASE64(key.getEncoded());
}
// 初始化密鑰
public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公鑰
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私鑰
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put("RSAPublicKey", publicKey);
keyMap.put("RSAPrivateKey", privateKey);
return keyMap;
}
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
*
* @param key
* @return * @throws Exception */ public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); }