Java消息摘要、對稱加密、非對稱加密和數字簽名

一、消息摘要

消息摘要是一種與消息認證結合使用以確保消息完整性的技術,消息摘要採用單向Hash函數將加密的明文“摘要”成一串密文,則這串密文亦稱爲數字指紋(Finger Print),則接受者通過對接受到信息的新產生的摘要與原摘要比較,就知道消息是否被修改了

特點:

  1. 唯一性
  2. 不可逆
  3. 不需要祕鑰
  4. 長度固定,無論輸入的明文有多長,計算出的消息摘要的長度總數固定的

原理:消息摘要就是將需要摘要的數據作爲參數,經過Hash函數計算,得到的散列值

常用消息摘要算法:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm, 安全散列算法)、MAC(Message AuthenticationCode,消息認證碼算法),目前廣泛使用算法MD5、SHA1

    @Test
    public void testMD() throws Exception {
        String plainText = "USE MD";
        System.out.println("明文:" + plainText);

        // 使用getInstance("算法")來獲得消息摘要
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        // 開始使用算法
        messageDigest.update(plainText.getBytes());
        // 得到摘要
        byte[] digestByte = messageDigest.digest();
        // 摘要長度始終爲16個字節,128位
        System.out.println("摘要長度:" + digestByte.length);

        // 輸出算法運算結果,防止亂碼,使用Base64編碼
        String encode = Base64.encodeBase64String(digestByte);
        System.out.println("摘要:" + encode);
    }

結果:

 

二、對稱加密

消息發送方和消息接收方必須使用相同的密鑰

對稱加密常用算法:DES(Data Encryption Standard, 數據加密標準)、AES(Advanced Encryption Standard, 高級加密標準)

    @Test
    public void testAES() throws Exception {
        String plainText = "USE AES";
        System.out.println("明文:" + plainText);

        // 得到一個使用AES算法的KeyGenerator的實例
        KeyGenerator kenGen = KeyGenerator.getInstance("AES");
        // 定義祕鑰長度128位
        kenGen.init(128);
        // 通過KeyGenerator產生一個key(祕鑰算法剛纔已定義,爲AES)
        Key key = kenGen.generateKey();

        // 1.獲取加密工具類,定義Cipher的基本信息,ECB是加密方法,PKCS5Padding是填充方法
        // 算法/工作模式/填充模式(algorithm/mode/padding
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

        // 2.加密,對工具類對象進行初始化
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 3.用加密工具類對象對明文進行加密
        byte[] encipherByte = cipher.doFinal(plainText.getBytes());
        String encode = Base64.encodeBase64String(encipherByte);
        System.out.println("加密:" + encode);

        // 2.解密
        cipher.init(Cipher.DECRYPT_MODE, key);
        // 3.用加密工具類對象對密文進行解密
        byte[] decode = Base64.decodeBase64(encode);
        byte[] decipherByte = cipher.doFinal(decode);
        String decipherText = new String(decipherByte);
        System.out.println("解密:" + decipherText);
    }

結果:

三、非對稱加密

非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)

非對稱加密常用算法:RSA

    @Test
    public void testRSA() throws Exception {
        String plainText = "USE RSA";
        System.out.println("明文:" + plainText);

        // 產生一個RSA祕鑰生成器KeyPairGenerator(一對鑰匙生成器)
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        // 定義祕鑰長度512位
        keyGen.initialize(512);
        // 通過KeyPairGenerator產生祕鑰,注意這裏的key是一對鑰匙
        KeyPair key = keyGen.generateKeyPair();

        // 1.獲取加密工具類
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

        // 2.使用公鑰加密,對工具類對象進行初始化
        cipher.init(Cipher.ENCRYPT_MODE, key.getPublic());
        // 3.用加密工具類對象對明文進行加密
        byte[] encipherByte = cipher.doFinal(plainText.getBytes());
        String encode = Base64.encodeBase64String(encipherByte);
        System.out.println("加密:" + encode);

        // 2.使用私鑰解密,對工具類對象進行初始化
        // PrivateKey privateKey = KeyFactory.getInstance("RSA")
        // .generatePrivate(new PKCS8EncodedKeySpec(key.getPrivate().getEncoded()));
        // cipher.init(Cipher.DECRYPT_MODE, privateKey);
        cipher.init(Cipher.DECRYPT_MODE, key.getPrivate());
        // 3.用加密工具類對象對密文進行解密
        byte[] decode = Base64.decodeBase64(encode);
        byte[] decipherByte = cipher.doFinal(decode);
        String decipherText = new String(decipherByte);
        System.out.println("解密:" + decipherText);
    }

結果:

四、數字簽名

數字簽名的主要作用就是保證了數據的有效性(驗證是誰發的)和完整性(證明信息沒有被篡改)

摘要經過加密,就得到數字簽名

簽名算法有:MD5withRSASHA1withRSASHA256withRSA

    @Test
    public void testSign() throws Exception {
        String plainText = "USE RSA TO SIGNATURE";
        System.out.println("正文:" + plainText);

        // 形成RSA公鑰對
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(512);
        KeyPair key = keyGen.generateKeyPair();

        // 1.獲取簽名工具類
        Signature sig = Signature.getInstance("MD5withRSA");
        // 2.初始化簽名,使用私鑰簽名
        sig.initSign(key.getPrivate());
        sig.update(plainText.getBytes());
        // 3.得到簽名
        byte[] signByte = sig.sign();
        String encode = Base64.encodeBase64String(signByte);
        System.out.println("簽名:" + encode);

        // 2.初始化驗證,使用公鑰驗證
        sig.initVerify(key.getPublic());
        sig.update(plainText.getBytes());
        // 3.進行驗證
        byte[] decode = Base64.decodeBase64(encode);
        if (sig.verify(decode)) {
            System.out.println("簽名驗證正確!");
        } else {
            System.out.println("簽名驗證失敗!");
        }
    }

結果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章