加密與數字證書

概念

數字摘要

數字摘要就是採用單項Hash函數將須要加密的明文「摘要」成一串固定長度(128位)的密文,這一串密文又稱爲數字指紋,HASH值或摘要值 ,它有固定的長度,並且不一樣的明文摘要成密文,其結果老是不一樣的,而一樣的明文其摘要一定一致。java

目前經常使用的摘要算法爲MD五、SHA一、SHA256等。其中MD5系列算法已經破解,通常再也不建議使用。 
MD5:Message-Digest Algorithm 5; 
SHA1:Secure Hash Algorithm;算法

密鑰加密技術

以用鑰匙鎖門爲例,鑰匙咱們能夠看作密鑰,鎖門的過程能夠看作加密過程,鎖門過程當中所用到的原理就是加密算法併發

私用密鑰(對稱加密)

採用單鑰密碼系統的加密方法,同一個密鑰能夠同時用做信息的加密和解密,這種加密方法稱爲對稱加密,也稱爲單密鑰加密。它的最大優點是加/解密速度快,適合於對大數據量進行加密,但密鑰管理困難。ide

公共密鑰(非對稱加密)

使用不一樣的密鑰來分別完成加密和解密操做,一個公開發布,即公開密鑰,另外一個由用戶本身祕密保存,即私用密鑰。信息發送者用公開密鑰去加密,而信息接收者則用私用密鑰去解密。公鑰機制靈活,但加密和解密速度卻比對稱密鑰加密慢得多。函數

非對稱加密的典型應用是數字簽名,加密密鑰。工具

數字簽名

數字簽名就是附加在數據單元上的一些數據,或是對數據單元所做的密碼變換。這種數據或變換容許數據單元的接收者用以確認數據單元的來源和數據單元的完整性並保護數據,防止被人(例如接收者)進行僞造。大數據

簽名過程:發送報文時,發送方用一個哈希函數從報文文本中生成報文摘要,而後用本身的私人密鑰對這個摘要進行加密,這個加密後的摘要將做爲報文的數字簽名和報文一塊兒發送給接收方。編碼

驗簽過程:接收方首先用與發送方同樣的哈希函數從接收到的原始報文中計算出報文摘要,接着再用發送方的公用密鑰來對報文附加的數字簽名進行解密,若是這兩個摘要相同、那麼接收方就能確認該數字簽名是發送方的。加密

數字簽名有兩種功效:一是能肯定消息確實是由發送方簽名併發出來的;二是數字簽名能肯定消息的完整性。spa

數字簽名是非對稱密鑰加密技術與數字摘要技術的應用。

下面是歐姆社系列圖書《漫畫密碼》截圖

數字證書的原理


數字證書的原理2

數字證書

數字證書提供了一種在Internet上驗證通訊實體身份的方式,其做用相似於司機的駕駛執照或平常生活中的身份證。它是由權威機構CA發行,人們能夠在網上用它來識別對方的身份。最簡單的證書包含一個公開密鑰、名稱以及證書受權中心的數字簽名,此外,數字證書只在特定的時間段內有效。 
數字證書是一個經證書受權中心數字簽名的包含公鑰擁有者信息以及公鑰的文件。

CA證書原理

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證書工具支持的證書私鑰格式

工具

keytool

keytool 是個密鑰和證書管理工具,它將密鑰和證書儲存在一個所謂的密鑰倉庫中。

  1. 密鑰實體(Key entity):密鑰(secret key)又或者是私鑰和配對公鑰(採用非對稱加密)

  2. 可信任的證書實體(trusted certificate entries):只包含公鑰

keytool經常使用命令:

修改密鑰別名:

keytool -changealias -alias ORIGALIAS -destalias NEWALIAS -keystore x.keystore 
輸入密鑰庫口令:密鑰庫密碼 
輸入<ORIGALIAS>的密鑰口令:密鑰密碼

導出證書 
keystore中的private key實體不包含公鑰,能夠經過導出到證書,再從證書中獲得公鑰:

keytool -export -alias ALIAS -keystore KEYSTORE -file PATH 
輸入密鑰庫口令:密鑰庫密碼


示例代碼

加密解密

密鑰庫準備

使用keytool工具生成一個密鑰實體:

keytool -genkey -alias origalias -keystore x.keystore

keytool list

而後須要將密鑰實體導出成證書,包含對應的公鑰:

keytool -export -alias origalias -keystore x.keystore -file origalias.cer

代碼

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"));
    }
}

簽名驗籤

代碼

簽名驗籤中使用的仍是上面代碼中的公鑰和私鑰

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);
相關文章
相關標籤/搜索