總結(jié)一些Java常用的加密算法
一、加密算法分類
加密算法通常分為三類:
對稱加密
指加密和解密使用相同密鑰的加密算法。對稱加密算法的優(yōu)點在于加解密效率高且易于實現(xiàn)。
不可逆加密
不可逆加密算法的特征是加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密,只有同樣輸入的輸入數(shù)據(jù)經(jīng)過同樣的不可逆算法才能得到同樣的加密數(shù)據(jù)。
非對稱加密
指加密和解密使用不同密鑰的加密算法,也稱為公私鑰加密。
二、加密算法的應(yīng)用
1.數(shù)字簽名:進行身份認證和數(shù)據(jù)完整性驗證,主要用到了非對稱密鑰加密技術(shù)與數(shù)字摘要技術(shù)。
2.數(shù)字證書:主要用來確保數(shù)字簽名才是安全有效的,數(shù)字證書由獨立的證書發(fā)行機構(gòu)發(fā)布。數(shù)字證書各不相同,每種證書可提供不同級別的可信度,該證書內(nèi)包含用戶的個人信息和他的公鑰信息,同時還附有認證中心的簽名信息。
3.MD5:對用戶密碼進行加密并進行保存。
4.網(wǎng)絡(luò)數(shù)據(jù)加密:保障傳輸?shù)臄?shù)據(jù)安全,即使被截獲報文,在沒有密匙的情況下也無法得知報文真實內(nèi)容。
5.SSL協(xié)議:在握手階段使用的是非對稱加密,在傳輸階段使用的是對稱加密,也就是說在SSL上傳送的數(shù)據(jù)是使用對稱密鑰加密的。同時HTTPS也是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸、身份認證(確認客戶端連接的目標主機是否是真實正確的主機)的網(wǎng)絡(luò)協(xié)議。
三、對稱加密算法實現(xiàn)
- 優(yōu)點:算法對消息雙方公開、計算量小、加密速度快、加密效率高。
- 缺點:在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好秘鑰,然后雙方保存好秘鑰。如果一方的秘鑰被泄露,那么加密信息就會被破解。
3.1 DES介紹
DES全稱為Data Encryption Standard,即數(shù)據(jù)加密標準,是一種使用密鑰加密的塊算法,1977年被美國聯(lián)邦政府的國家標準局確定為聯(lián)邦資料處理標準(FIPS),并授權(quán)在非密級政府通信中使用,隨后該算法在國際上廣泛流傳開來。不過現(xiàn)在已經(jīng)有點過時了。
Java代碼實現(xiàn):
import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import javax.crypto.spec.DESKeySpec; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKey; import javax.crypto.Cipher; /** * DES加密介紹 DES是一種對稱加密算法,所謂對稱加密算法即:加密和解密使用相同密鑰的算法。DES加密算法出自IBM的研究, * 后來被美國政府正式采用,之后開始廣泛流傳,但是近些年使用越來越少,因為DES使用56位密鑰,以現(xiàn)代計算能力, * 24小時內(nèi)即可被破解。雖然如此,在某些簡單應(yīng)用中,我們還是可以使用DES加密算法,本文簡單講解DES的JAVA實現(xiàn) 。 * 注意:DES加密和解密過程中,密鑰長度都必須是8的倍數(shù) */ public class DesDemo { public DesDemo() { } // 測試 public static void main(String args[]) { // 待加密內(nèi)容 String str = "cryptology"; // 密碼,長度要是8的倍數(shù) String password = "95880288"; byte[] result; try { result = DesDemo.encrypt(str.getBytes(), password); System.out.println("加密后:" + result); byte[] decryResult = DesDemo.decrypt(result, password); System.out.println("解密后:" + new String(decryResult)); } catch (UnsupportedEncodingException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } catch (Exception e1) { e1.printStackTrace(); } } // 直接將如上內(nèi)容解密 /** * 加密 * * @param datasource * byte[] * @param password * String * @return byte[] */ public static byte[] encrypt(byte[] datasource, String password) { try { SecureRandom random = new SecureRandom(); DESKeySpec desKey = new DESKeySpec(password.getBytes()); // 創(chuàng)建一個密匙工廠,然后用它把DESKeySpec轉(zhuǎn)換成 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(desKey); // Cipher對象實際完成加密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher對象,ENCRYPT_MODE用于將 Cipher 初始化為加密模式的常量 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); // 現(xiàn)在,獲取數(shù)據(jù)并加密 // 正式執(zhí)行加密操作 return cipher.doFinal(datasource); // 按單部分操作加密或解密數(shù)據(jù),或者結(jié)束一個多部分操作 } catch (Throwable e) { e.printStackTrace(); } return null; } /** * 解密 * * @param src * byte[] * @param password * String * @return byte[] * @throws Exception */ public static byte[] decrypt(byte[] src, String password) throws Exception { // DES算法要求有一個可信任的隨機數(shù)源 SecureRandom random = new SecureRandom(); // 創(chuàng)建一個DESKeySpec對象 DESKeySpec desKey = new DESKeySpec(password.getBytes()); // 創(chuàng)建一個密匙工廠 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 返回實現(xiàn)指定轉(zhuǎn)換的 // Cipher // 對象 // 將DESKeySpec對象轉(zhuǎn)換成SecretKey對象 SecretKey securekey = keyFactory.generateSecret(desKey); // Cipher對象實際完成解密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher對象 cipher.init(Cipher.DECRYPT_MODE, securekey, random); // 真正開始解密操作 return cipher.doFinal(src); } }
3.2 IDEA介紹
- 這種算法是在DES算法的基礎(chǔ)上發(fā)展出來的,類似于三重DES。
- 發(fā)展IDEA也是因為感到DES具有密鑰太短等缺點。
- DEA的密鑰為128位,這么長的密鑰在今后若干年內(nèi)應(yīng)該是安全的。
- 在實際項目中用到的很少了解即可。
Java代碼實現(xiàn)
import java.security.Key; import java.security.Security; 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 org.bouncycastle.jce.provider.BouncyCastleProvider; public class IDEADemo { public static void main(String args[]) { bcIDEA(); } public static void bcIDEA() { String src = "www.xttblog.com security idea"; try { Security.addProvider(new BouncyCastleProvider()); //生成key KeyGenerator keyGenerator = KeyGenerator.getInstance("IDEA"); keyGenerator.init(128); SecretKey secretKey = keyGenerator.generateKey(); byte[] keyBytes = secretKey.getEncoded(); //轉(zhuǎn)換密鑰 Key key = new SecretKeySpec(keyBytes, "IDEA"); //加密 Cipher cipher = Cipher.getInstance("IDEA/ECB/ISO10126Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("bc idea encrypt : " + Base64.encodeBase64String(result)); //解密 cipher.init(Cipher.DECRYPT_MODE, key); result = cipher.doFinal(result); System.out.println("bc idea decrypt : " + new String(result)); } catch (Exception e) { e.printStackTrace(); } } }
四、不可逆加密算法
- 優(yōu)點:不可逆、易計算、特征化
- 缺點:可能存在散列沖突
4.1 MD5介紹
MD5的作用是讓大容量信息在用數(shù)字簽名軟件簽署私人密鑰前被"壓縮"成一種保密的格式
(也就是把一個任意長度的字節(jié)串變換成一定長的十六進制數(shù)字串)。
主要有以下特點:
- 1.壓縮性: 任意長度的數(shù)據(jù),算出的MD5值長度都是固定的。
- 2.容易計算: 從原數(shù)據(jù)計算出MD5值很容易。
- 3.抗修改性: 對原數(shù)據(jù)進行任何改動,哪怕只修改1個字節(jié),所得到的MD5值都有很大區(qū)別。
- 4.強抗碰撞: 已知原數(shù)據(jù)和其MD5值,想找到一個具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。
Java代碼實現(xiàn)
import java.security.MessageDigest; //利用JDK提供java.security.MessageDigest類實現(xiàn)MD5算法 public class MD5Demo { public static void main(String[] args) { System.out.println(getMD5Code("不可逆加密算法")); } private MD5Demo() { } // md5加密 public static String getMD5Code(String message) { String md5Str = ""; try { //創(chuàng)建MD5算法消息摘要 MessageDigest md = MessageDigest.getInstance("MD5"); //生成的哈希值的字節(jié)數(shù)組 byte[] md5Bytes = md.digest(message.getBytes()); md5Str = bytes2Hex(md5Bytes); }catch(Exception e) { e.printStackTrace(); } return md5Str; } // 2進制轉(zhuǎn)16進制 public static String bytes2Hex(byte[] bytes) { StringBuffer result = new StringBuffer(); int temp; try { for (int i = 0; i < bytes.length; i++) { temp = bytes[i]; if(temp < 0) { temp += 256; } if (temp < 16) { result.append("0"); } result.append(Integer.toHexString(temp)); } } catch (Exception e) { e.printStackTrace(); } return result.toString(); } }
4.2 SHA1介紹
對于長度小于2^64位的消息,SHA1會產(chǎn)生一個160位(40個字符)的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數(shù)據(jù)的完整性。在傳輸?shù)倪^程中,數(shù)據(jù)很可能會發(fā)生變化,那么這時候就會產(chǎn)生不同的消息摘要。
SHA1有如下特性:
- 不可以從消息摘要中復(fù)原信息;
- 兩個不同的消息不會產(chǎn)生同樣的消息摘要,(但會有1x10 ^ 48分之一的機率出現(xiàn)相同的消息摘要,一般使用時忽略)。
Java代碼實現(xiàn)
import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHA1Demo { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(getSha1("不可逆加密算法")); } public static String getSha1(String str) { if (null == str || 0 == str.length()) { return null; } char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { //創(chuàng)建SHA1算法消息摘要對象 MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); //使用指定的字節(jié)數(shù)組更新摘要。 mdTemp.update(str.getBytes("UTF-8")); //生成的哈希值的字節(jié)數(shù)組 byte[] md = mdTemp.digest(); //SHA1算法生成信息摘要關(guān)鍵過程 int j = md.length; char[] buf = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return "0"; } }
4.3 HMAC 介紹
HMAC 是密鑰相關(guān)的 哈希運算消息認證碼(Hash-based Message Authentication Code),HMAC 運算利用 哈希算法 (MD5、SHA1 等),以 一個密鑰 和 一個消息 為輸入,生成一個 消息摘要 作為 輸出。
HMAC 發(fā)送方 和 接收方 都有的 key 進行計算,而沒有這把 key 的第三方,則是 無法計算 出正確的 散列值的,這樣就可以 防止數(shù)據(jù)被篡改。
Java代碼實現(xiàn)
import net.pocrd.annotation.NotThreadSafe; import net.pocrd.define.ConstField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays; @NotThreadSafe public class HMacHelper { private static final Logger logger = LoggerFactory.getLogger(HMacHelper.class); private Mac mac; /** * MAC算法可選以下多種算法 * HmacMD5/HmacSHA1/HmacSHA256/HmacSHA384/HmacSHA512 */ private static final String KEY_MAC = "HmacMD5"; public HMacHelper(String key) { try { SecretKey secretKey = new SecretKeySpec(key.getBytes(ConstField.UTF8), KEY_MAC); mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); } catch (Exception e) { logger.error("create hmac helper failed.", e); } } public byte[] sign(byte[] content) { return mac.doFinal(content); } public boolean verify(byte[] signature, byte[] content) { try { byte[] result = mac.doFinal(content); return Arrays.equals(signature, result); } catch (Exception e) { logger.error("verify sig failed.", e); } return false; } }
五、非對稱加密
- 優(yōu)點:非對稱加密與對稱加密相比其安全性更好,只要私鑰不泄露,很難被破解。
- 缺點:加密和解密花費時間長、速度慢,只適合對少量數(shù)據(jù)進行加密。
5.1 RSA介紹
RSA是目前最有影響力和最常用的公鑰加密算法。它能夠抵抗到目前為止已知的絕大多數(shù)密碼攻擊,已被ISO推薦為公鑰數(shù)據(jù)加密標準。RSA公開密鑰密碼體制的原理是:根據(jù)數(shù)論,尋求兩個大素數(shù)比較簡單,而將它們的乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰
Java代碼實現(xiàn)
import org.apache.commons.codec.binary.Base64; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; /** * Created by humf.需要依賴 commons-codec 包 */ public class RSADemo { public static void main(String[] args) throws Exception { Map<String, Key> keyMap = initKey(); String publicKey = getPublicKey(keyMap); String privateKey = getPrivateKey(keyMap); System.out.println(keyMap); System.out.println("-----------------------------------"); System.out.println(publicKey); System.out.println("-----------------------------------"); System.out.println(privateKey); System.out.println("-----------------------------------"); byte[] encryptByPrivateKey = encryptByPrivateKey("123456".getBytes(), privateKey); byte[] encryptByPublicKey = encryptByPublicKey("123456", publicKey); System.out.println(encryptByPrivateKey); System.out.println("-----------------------------------"); System.out.println(encryptByPublicKey); System.out.println("-----------------------------------"); String sign = sign(encryptByPrivateKey, privateKey); System.out.println(sign); System.out.println("-----------------------------------"); boolean verify = verify(encryptByPrivateKey, publicKey, sign); System.out.println(verify); System.out.println("-----------------------------------"); byte[] decryptByPublicKey = decryptByPublicKey(encryptByPrivateKey, publicKey); byte[] decryptByPrivateKey = decryptByPrivateKey(encryptByPublicKey, privateKey); System.out.println(decryptByPublicKey); System.out.println("-----------------------------------"); System.out.println(decryptByPrivateKey); } public static final String KEY_ALGORITHM = "RSA"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; private static final String PUBLIC_KEY = "RSAPublicKey"; private static final String PRIVATE_KEY = "RSAPrivateKey"; public static byte[] decryptBASE64(String key) { return Base64.decodeBase64(key); } public static String encryptBASE64(byte[] bytes) { return Base64.encodeBase64String(bytes); } /** * 用私鑰對信息生成數(shù)字簽名 * * @param data * 加密數(shù)據(jù) * @param privateKey * 私鑰 * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64編碼的私鑰 byte[] keyBytes = decryptBASE64(privateKey); // 構(gòu)造PKCS8EncodedKeySpec對象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私鑰匙對象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數(shù)字簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校驗數(shù)字簽名 * * @param data * 加密數(shù)據(jù) * @param publicKey * 公鑰 * @param sign * 數(shù)字簽名 * @return 校驗成功返回true 失敗返回false * @throws Exception */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { // 解密由base64編碼的公鑰 byte[] keyBytes = decryptBASE64(publicKey); // 構(gòu)造X509EncodedKeySpec對象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取公鑰匙對象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); 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(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數(shù)據(jù)解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPrivateKey(String data, String key) throws Exception { return decryptByPrivateKey(decryptBASE64(data), key); } /** * 解密<br> * 用公鑰解密 * * @param data * @param key * @return * @throws Exception */ public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception { // 對密鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對數(shù)據(jù)解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * 加密<br> * 用公鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptByPublicKey(String data, String key) throws Exception { // 對公鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得公鑰 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); // 對數(shù)據(jù)加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data.getBytes()); } /** * 加密<br> * 用私鑰加密 * * @param data * @param key * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception { // 對密鑰解密 byte[] keyBytes = decryptBASE64(key); // 取得私鑰 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 對數(shù)據(jù)加密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); } /** * 取得私鑰 * * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Key> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公鑰 * * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Key> keyMap) throws Exception { Key key = keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } /** * 初始化密鑰 * * @return * @throws Exception */ public static Map<String, Key> initKey() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); Map<String, Key> keyMap = new HashMap(2); keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公鑰 keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私鑰 return keyMap; } }
5.2 ECC 介紹
ECC
也是一種 非對稱加密算法,主要優(yōu)勢是在某些情況下,它比其他的方法使用 更小的密鑰,比如 RSA
加密算法,提供 相當?shù)幕蚋叩燃?/strong> 的安全級別。不過一個缺點是 加密和解密操作 的實現(xiàn)比其他機制 時間長 (相比 RSA
算法,該算法對 CPU
消耗嚴重)。
Java代碼實現(xiàn)
import net.pocrd.annotation.NotThreadSafe; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.KeyFactory; import java.security.Security; import java.security.Signature; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; @NotThreadSafe public class EccHelper { private static final Logger logger = LoggerFactory.getLogger(EccHelper.class); private static final int SIZE = 4096; private BCECPublicKey publicKey; private BCECPrivateKey privateKey; static { Security.addProvider(new BouncyCastleProvider()); } public EccHelper(String publicKey, String privateKey) { this(Base64Util.decode(publicKey), Base64Util.decode(privateKey)); } public EccHelper(byte[] publicKey, byte[] privateKey) { try { KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); if (publicKey != null && publicKey.length > 0) { this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey)); } if (privateKey != null && privateKey.length > 0) { this.privateKey = (BCECPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey)); } } catch (ClassCastException e) { throw new RuntimeException("", e); } catch (Exception e) { throw new RuntimeException(e); } } public EccHelper(String publicKey) { this(Base64Util.decode(publicKey)); } public EccHelper(byte[] publicKey) { try { KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); if (publicKey != null && publicKey.length > 0) { this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey)); } } catch (Exception e) { throw new RuntimeException(e); } } public byte[] encrypt(byte[] content) { if (publicKey == null) { throw new RuntimeException("public key is null."); } try { Cipher cipher = Cipher.getInstance("ECIES", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int size = SIZE; ByteArrayOutputStream baos = new ByteArrayOutputStream((content.length + size - 1) / size * (size + 45)); int left = 0; for (int i = 0; i < content.length; ) { left = content.length - i; if (left > size) { cipher.update(content, i, size); i += size; } else { cipher.update(content, i, left); i += left; } baos.write(cipher.doFinal()); } return baos.toByteArray(); } catch (Exception e) { throw new RuntimeException(e); } } public byte[] decrypt(byte[] secret) { if (privateKey == null) { throw new RuntimeException("private key is null."); } try { Cipher cipher = Cipher.getInstance("ECIES", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey); int size = SIZE + 45; ByteArrayOutputStream baos = new ByteArrayOutputStream((secret.length + size + 44) / (size + 45) * size); int left = 0; for (int i = 0; i < secret.length; ) { left = secret.length - i; if (left > size) { cipher.update(secret, i, size); i += size; } else { cipher.update(secret, i, left); i += left; } baos.write(cipher.doFinal()); } return baos.toByteArray(); } catch (Exception e) { logger.error("ecc decrypt failed.", e); } return null; } public byte[] sign(byte[] content) { if (privateKey == null) { throw new RuntimeException("private key is null."); } try { Signature signature = Signature.getInstance("SHA1withECDSA", "BC"); signature.initSign(privateKey); signature.update(content); return signature.sign(); } catch (Exception e) { throw new RuntimeException(e); } } public boolean verify(byte[] sign, byte[] content) { if (publicKey == null) { throw new RuntimeException("public key is null."); } try { Signature signature = Signature.getInstance("SHA1withECDSA", "BC"); signature.initVerify(publicKey); signature.update(content); return signature.verify(sign); } catch (Exception e) { logger.error("ecc verify failed.", e); } return false; } }
到此這篇關(guān)于總結(jié)一些Java常用的加密算法的文章就介紹到這了,更多相關(guān)Java加密算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java注解機制之Spring自動裝配實現(xiàn)原理詳解
這篇文章主要為大家詳細介紹了Java注解機制之Spring自動裝配實現(xiàn)原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10SSH框架網(wǎng)上商城項目第11戰(zhàn)之查詢和刪除商品功能實現(xiàn)
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第11戰(zhàn)之查詢和刪除商品功能實現(xiàn)的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-06-06Java實現(xiàn)對視頻進行截圖的方法【附ffmpeg下載】
這篇文章主要介紹了Java實現(xiàn)對視頻進行截圖的方法,結(jié)合實例形式分析了Java使用ffmpeg針對視頻進行截圖的相關(guān)操作技巧,并附帶ffmpeg.exe文件供讀者下載使用,需要的朋友可以參考下2018-01-01MyBatisPlus-QueryWrapper多條件查詢及修改方式
這篇文章主要介紹了MyBatisPlus-QueryWrapper多條件查詢及修改方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06詳解Spring與Mybatis整合方法(基于IDEA中的Maven整合)
這篇文章主要介紹了Spring與Mybatis整合方法(基于IDEA中的Maven整合),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10Java中的關(guān)鍵字_動力節(jié)點Java學院整理
關(guān)鍵字也稱為保留字,是指Java語言中規(guī)定了特定含義的標示符。對于保留字,用戶只能按照系統(tǒng)規(guī)定的方式使用,不能自行定義2017-04-04