原創(chuàng):扣釘日記(微信公眾號ID:codelogs) , 歡迎分享 , 轉(zhuǎn)載請保留出處 。簡介前面在密碼學(xué)入門一文中講解了各種常見的密碼學(xué)概念、算法與運(yùn)用場景 , 但沒有介紹過代碼 , 因此 , 為作補(bǔ)充 , 這一篇將會介紹使用Java語言如何實(shí)現(xiàn)使用這些算法 , 并介紹一下使用過程中可能遇到的坑 。
Java加密體系JCAJava抽象了一套密碼算法框架JCA(Java Cryptography Architecture) , 在此框架中定義了一套接口與類 , 以規(guī)范Java平臺密碼算法的實(shí)現(xiàn) , 而Sun , SunRsaSign , SunJCE這些則是一個(gè)個(gè)JCA的實(shí)現(xiàn)Provider , 以實(shí)現(xiàn)具體的密碼算法 , 這有點(diǎn)像List與ArrayList、LinkedList的關(guān)系一樣 , Java開發(fā)者只需要使用JCA即可 , 而不用管具體是怎么實(shí)現(xiàn)的 。
JCA里定義了一系列類 , 如Cipher、MessageDigest、MAC、Signature等 , 分別用于實(shí)現(xiàn)加密、密碼學(xué)哈希、認(rèn)證碼、數(shù)字簽名等算法 , 一起來看看吧!
對稱加密對稱加密算法 , 使用Cipher類即可 , 以廣泛使用的AES為例 , 如下:
public byte[] encrypt(byte[] data, Key key) {try {Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");byte[] iv = SecureRandoms.randBytes(cipher.getBlockSize());//初始化密鑰與加密參數(shù)ivcipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));//加密byte[] encryptBytes = cipher.doFinal(data);//將iv與密文拼在一起B(yǎng)yteArrayOutputStream baos = new ByteArrayOutputStream(iv.length + encryptBytes.length);baos.write(iv);baos.write(encryptBytes);return baos.toByteArray();} catch (Exception e) {return ExceptionUtils.rethrow(e);}}public byte[] decrypt(byte[] data, Key key) {try {Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//獲取密文前面的ivIvParameterSpec ivSpec = new IvParameterSpec(data, 0, cipher.getBlockSize());cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);//解密iv后面的密文return cipher.doFinal(data, cipher.getBlockSize(), data.length - cipher.getBlockSize());} catch (Exception e) {return ExceptionUtils.rethrow(e);}}如上 , 對稱加密主要使用Cipher , 不管是AES還是DES , Cipher.getInstance()傳入不同的算法名稱即可 , 這里的Key參數(shù)就是加密時(shí)使用的密鑰 , 稍后會介紹它是怎么來的 , 暫時(shí)先忽略它 。另外 , 為了使得每次加密出來的密文不同 , 我使用了隨機(jī)的iv向量 , 并將iv向量拼接在了密文前面 。注:如果某個(gè)算法名稱 , 如上面的非對稱加密非對稱加密同樣是使用Cipher類 , 只是傳入的密鑰對象不同 , 以RSA算法為例 , 如下:AES/CBC/PKCS5Padding, 你不知道它在JCA中的標(biāo)準(zhǔn)名稱是什么 , 可以到 https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html 中查詢即可 。
public byte[] encryptByPublicKey(byte[] data, PublicKey publicKey){try{Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}catch (Exception e) {throw Errors.toRuntimeException(e);}}public byte[] decryptByPrivateKey(byte[] data, PrivateKey privateKey){try{Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(data);}catch (Exception e) {throw Errors.toRuntimeException(e);}}一般來說應(yīng)使用公鑰加密 , 私鑰解密 , 但其實(shí)反過來也是可以的 , 這里的PublicKey與PrivateKey也先忽略 , 后面會介紹它怎么來的 。
經(jīng)驗(yàn)總結(jié)擴(kuò)展閱讀
- [WPF] 抄抄超強(qiáng)的蘋果官網(wǎng)滾動文字特效實(shí)現(xiàn)
- Java函數(shù)式編程:一、函數(shù)式接口,lambda表達(dá)式和方法引用
- 不妨試試更快更小更靈活Java開發(fā)框架Solon
- 11 微服務(wù)架構(gòu)學(xué)習(xí)與思考:開源 API 網(wǎng)關(guān)02-以 Java 為基礎(chǔ)的 API 網(wǎng)關(guān)詳細(xì)介紹
- java 新特性之 Stream API
- java 入土--集合詳解
- 4 Java I/O:AIO和NIO中的Selector
- 2023容易暴富的星座女實(shí)現(xiàn)質(zhì)的飛躍
- 通過 Github Action 實(shí)現(xiàn)定時(shí)推送天氣預(yù)報(bào)
- 3 Java I/O:NIO中的Buffer
