java加密與數字證書
數字摘要
數字摘要就是采用單項Hash函數將需要加密的明文“摘要”成一串固定長度(128位)的密文,這一串密文又稱為數字指紋,HASH值或摘要值 ,它有固定的長度,而且不同的明文摘要成密文,其結果總是不同的,而同樣的明文其摘要必定一致。
目前常用的摘要算法為MD5、SHA1、SHA256等。其中MD5系列算法已經破解,一般不再建議使用。
MD5:Message-Digest Algorithm 5;
SHA1:Secure Hash Algorithm;
密鑰加密技術
以用鑰匙鎖門為例,鑰匙我們可以看做密鑰,鎖門的過程可以看做加密過程,鎖門過程中所用到的原理就是加密算法
私用密鑰(對稱加密)
采用單鑰密碼系統的加密方法,同一個密鑰可以同時用作信息的加密和解密,這種加密方法稱為對稱加密,也稱為單密鑰加密。它的最大優勢是加/解密速度快,適合于對大數據量進行加密,但密鑰管理困難。
公共密鑰(非對稱加密)
使用不同的密鑰來分別完成加密和解密操作,一個公開發布,即公開密鑰,另一個由用戶自己秘密保存,即私用密鑰。信息發送者用公開密鑰去加密,而信息接收者則用私用密鑰去解密。公鑰機制靈活,但加密和解密速度卻比對稱密鑰加密慢得多。
非對稱加密的典型應用是數字簽名,加密密鑰。
數字簽名
數字簽名就是附加在數據單元上的一些數據,或是對數據單元所作的密碼變換。這種數據或變換允許數據單元的接收者用以確認數據單元的來源和數據單元的完整性并保護數據,防止被人(例如接收者)進行偽造。
簽名過程:發送報文時,發送方用一個哈希函數從報文文本中生成報文摘要,然后用自己的私人密鑰對這個摘要進行加密,這個加密后的摘要將作為報文的數字簽名和報文一起發送給接收方。
驗簽過程:接收方首先用與發送方一樣的哈希函數從接收到的原始報文中計算出報文摘要,接著再用發送方的公用密鑰來對報文附加的數字簽名進行解密,如果這兩個摘要相同、那么接收方就能確認該數字簽名是發送方的。
</blockquote>數字簽名有兩種功效:一是能確定消息確實是由發送方簽名并發出來的;二是數字簽名能確定消息的完整性。
數字簽名是非對稱密鑰加密技術與數字摘要技術的應用。
下面是歐姆社系列圖書《漫畫密碼》截圖
</blockquote>
![]()
</blockquote>
![]()
數字證書
數字證書提供了一種在Internet上驗證通信實體身份的方式,其作用類似于司機的駕駛執照或日常生活中的身份證。它是由權威機構CA發行,人們可以在網上用它來識別對方的身份。最簡單的證書包含一個公開密鑰、名稱以及證書授權中心的數字簽名,此外,數字證書只在特定的時間段內有效。
數字證書是一個經證書授權中心數字簽名的包含公鑰擁有者信息以及公鑰的文件。</blockquote>
![]()
X.509標準
X.509是由國際電信聯盟(ITU-T)制定的數字證書標準。
擴展文件:
- .cer, .crt - 通常被用于二進制的DER文件格式(同于.der),不過也被用于Base64編碼的文件 (例如 .pem),保存證書的公鑰
- .P7B - 同于 .p7c
- .P7C - PKCS#7證書格式,僅僅包含證書和CRL列表信息,沒有私鑰。
- .PFX - 同于 .p12
- .P12 -PKCS#12文件,包含證書(公鑰)和私鑰(受密碼保護),已經完整的證書鏈信
- .jks - JAVA的keytools證書工具支持的證書私鑰格式
</ul>工具
keytool
keytool 是個密鑰和證書管理工具,它將密鑰和證書儲存在一個所謂的密鑰倉庫中。
- 密鑰實體(Key entity):密鑰(secret key)又或者是私鑰和配對公鑰(采用非對稱加密)
- 可信任的證書實體(trusted certificate entries):只包含公鑰
</ol>keytool常用命令:
command? description </tr> </tbody>-genkey 生成密鑰 </tr>-alias 指定密鑰別名 </tr>-keystore 指定密鑰庫的名稱 </tr>-storepass 指定密鑰庫的密碼 </tr>-validity 指定證書有效期 </tr>-keyalg 指定密鑰的算法,默認采用DSA </tr>-keysize 指定密鑰長度 </tr>-keypass 指定別名對應密鑰的密碼(私鑰的密碼) </tr>-dname 指定證書所有者信息 </tr>-list 顯示密鑰庫中的證書信息 </tr>-v 顯示密鑰庫中的證書詳細信息 </tr>-file 指定證書的路徑名稱 </tr>-delete 刪除密鑰庫中某條目 </tr>-printcert 查看導出的證書信息 </tr>-keypasswd 修改密鑰庫中指定條目口令 </tr>-export 將別名指定的證書導出到文件 </tr>-import 將已簽名數字證書導入密鑰庫 </tr> </tbody> </table>修改密鑰別名:
keytool -changealias -alias ORIGALIAS -destalias NEWALIAS -keystore x.keystore
</blockquote>
輸入密鑰庫口令:密鑰庫密碼
輸入<ORIGALIAS>的密鑰口令:密鑰密碼導出證書
keystore中的private key實體不包含公鑰,可以通過導出到證書,再從證書中得到公鑰:keytool -export -alias ALIAS -keystore KEYSTORE -file PATH
</blockquote>
輸入密鑰庫口令:密鑰庫密碼
示例代碼
加密解密
密鑰庫準備
使用keytool工具生成一個密鑰實體:
keytool -genkey -alias origalias -keystore x.keystore
</blockquote>
![]()
然后需要將密鑰實體導出成證書,包含對應的公鑰:
keytool -export -alias origalias -keystore x.keystore -file origalias.cer
</blockquote>代碼
public class Demo { private static String STOREPATH = "C:/Users/Hang/x.keystore"; private static String STOREPASS = "123456"; private static String KEYALIAS = "origalias"; private static String KEYPASS = "111111"; private static String CERTPATH = "C:/Users/Hang/origalias.cer"; private static String CERTPASS = "111111"; private static String SignAlg = "SHA256withRSA";/* 拋出異常:KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException, UnrecoverableKeyException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, SignatureException */ public static void main(String[] args) throws Exception { //根據密鑰庫類型JKS得到密鑰庫實例 KeyStore keyStore = KeyStore.getInstance("JKS","SUN"); InputStream in = new FileInputStream(STOREPATH); keyStore.load(in, STOREPASS.toCharArray()); //根據alias從keystone中取出密鑰對 PrivateKey privateKey = null; if(keyStore.isKeyEntry(KEYALIAS)){ privateKey = (PrivateKey) keyStore.getKey(KEYALIAS, KEYPASS.toCharArray()); } //使用命令導出密鑰的證書`keytool -export -alias origalias -keystore x.keystore -file origalias.jks` //加載證書 //證書格式為X509 CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); //讀取證書文件的輸入流 InputStream certin = new FileInputStream(CERTPATH); Certificate certificate = certificateFactory.generateCertificate(certin); //從證書中得到公鑰 PublicKey publicKey = certificate.getPublicKey(); System.out.println("私鑰:\r\n"+privateKey); System.out.println("公鑰:\r\n"+publicKey); String source = "X.509是由國際電信聯盟(ITU-T)制定的數字證書標準。"; Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, privateKey); cipher.update("數字簽名是 非對稱密鑰加密技術與數字摘要技術的應用。\r\n".getBytes("UTF-8")); byte[] cipherByte = cipher.doFinal(source.getBytes("UTF-8")); cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] decrpytByte = cipher.doFinal(cipherByte); System.out.println(new String(decrpytByte,"UTF-8")); }
}</pre>
簽名驗簽
代碼
簽名驗簽中使用的還是上面代碼中的公鑰和私鑰
Signature signature = Signature.getInstance(SignAlg); signature.initSign(privateKey); signature.update("數字簽名是 非對稱密鑰加密技術與數字摘要技術的應用。\r\n".getBytes("UTF-8")); signature.update(source.getBytes("UTF-8")); byte[] signByte = signature.sign();signature.initVerify(certificate); //certificate 和 publicKey都可以驗簽 signature.update("數字簽名是 非對稱密鑰加密技術與數字摘要技術的應用。\r\n".getBytes("UTF-8")); signature.update(source.getBytes("UTF-8")); boolean verified = signature.verify(signByte); System.out.println(verified);**</em></pre><em> <p>來自:http://my.oschina.net/sherwayne/blog/353818<br />
</p> </em>
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關資訊
sesese色