主頁 > 區塊鏈 > 密碼學DAY2

密碼學DAY2

2020-09-10 03:05:42 區塊鏈

目錄

  • 1.1 加密模式
  • 1.2 填充模式
  • 1.3 訊息摘要
    • 1.3.1 特點
    • 1.3.2 獲取字串訊息摘要
    • 1.3.3 base64編碼
    • 1.3.4 其他數字摘要演算法
    • 1.3.5 獲取檔案訊息摘要
  • 1.4 非對稱加密
    • 1.4.1 生成公鑰和私鑰
    • 1.4.2 私鑰加密
    • 1.4.3 私鑰加密私鑰解密
    • 1.4.4 私鑰加密公鑰解密
  • 1.5 數字簽名
    • 1.5.1 簡單認識
    • 1.5.2 基本原理
    • 1.5.3 數字證書
    • 1.5.4 代碼實作

1.1 加密模式

加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html

ECB
ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進行獨立加密

  • 優點 : 可以并行處理資料
  • 缺點 : 同樣的原文生成同樣的密文, 不能很好的保護資料
  • 同時加密,原文是一樣的,加密出來的密文也是一樣的

CBC
CBC : Cipher-block chaining, 密碼塊鏈接. 每個明文塊先與前一個密文塊進行異或后,再進行加密,在這種方法中,每個密文塊都依賴于它前面的所有明文塊

  • 優點 : 同樣的原文生成的密文不一樣
  • 缺點 : 串行處理資料

1.2 填充模式

  • 當需要按塊處理的資料, 資料長度不符合塊處理需求時, 按照一定的方法填充滿塊長的規則
    NoPadding

  • 不填充.
    -在DES加密演算法下, 要求原文長度必須是8byte的整數倍
    -在AES加密演算法下, 要求原文長度必須是16byte的整數倍
    PKCS5Padding

  • 資料塊的大小為8位, 不夠就補足

Tips

  • 默認情況下, 加密模式和填充模式為 : ECB/PKCS5Padding
  • 如果使用CBC模式, 在初始化Cipher物件時, 需要增加引數, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());

加密模式和填充模式

AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)

加密模式和填充模式例子

package com.atguigu.desaes;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class DesDemo {
    // DES加密演算法,key的大小必須是8個位元組

    public static void main(String[] args) throws Exception {
        String input ="硅谷";
        // DES加密演算法,key的大小必須是8個位元組
        String key = "12345678";
        // 指定獲取Cipher的演算法,如果沒有指定加密模式和填充模式,ECB/PKCS5Padding就是默認值
        //     String transformation = "DES"; // 9PQXVUIhaaQ=
        //String transformation = "DES/ECB/PKCS5Padding"; // 9PQXVUIhaaQ=
        // CBC模式,必須指定初始向量,初始向量中密鑰的長度必須是8個位元組
        //String transformation = "DES/CBC/PKCS5Padding"; // 9PQXVUIhaaQ=
        // NoPadding模式,原文的長度必須是8個位元組的整倍數 ,所以必須把 硅谷改成硅谷12
        String transformation = "DES/CBC/NoPadding"; // 9PQXVUIhaaQ=
        // 指定獲取密鑰的演算法
        String algorithm = "DES";
        String encryptDES = encryptDES(input, key, transformation, algorithm);
        System.out.println("加密:" + encryptDES);
//        String s = dncryptDES(encryptDES, key, transformation, algorithm);
//        System.out.println("解密:" + s);

    }

    /**
     * 使用DES加密資料
     *
     * @param input          : 原文
     * @param key            : 密鑰(DES,密鑰的長度必須是8個位元組)
     * @param transformation : 獲取Cipher物件的演算法
     * @param algorithm      : 獲取密鑰的演算法
     * @return : 密文
     * @throws Exception
     */
    private static String encryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 獲取加密物件
        Cipher cipher = Cipher.getInstance(transformation);
        // 創建加密規則
        // 第一個引數key的位元組
        // 第二個引數表示加密演算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        // ENCRYPT_MODE:加密模式
        // DECRYPT_MODE: 解密模式
         // 初始向量,引數表示跟誰進行異或,初始向量的長度必須是8位
//        IvParameterSpec iv = new IvParameterSpec(key.getBytes());
         // 初始化加密模式和演算法
        cipher.init(Cipher.ENCRYPT_MODE,sks);
        // 加密
        byte[] bytes = cipher.doFinal(input.getBytes());

        // 輸出加密后的資料
        String encode = Base64.encode(bytes);

        return encode;
    }

    /**
     * 使用DES解密
     *
     * @param input          : 密文
     * @param key            : 密鑰
     * @param transformation : 獲取Cipher物件的演算法
     * @param algorithm      : 獲取密鑰的演算法
     * @throws Exception
     * @return: 原文
     */
    private static String dncryptDES(String input, String key, String transformation, String algorithm) throws Exception {
        // 1,獲取Cipher物件
        Cipher cipher = Cipher.getInstance(transformation);
        // 指定密鑰規則
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
//        IvParameterSpec iv = new IvParameterSpec(key.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, sks);
        // 3. 解密
        byte[] bytes = cipher.doFinal(Base64.decode(input));

        return new String(bytes);
    }
}

運行程式:

1.3 訊息摘要

  • 訊息摘要(Message Digest)又稱為數字摘要(Digital Digest)
  • 它是一個唯一對應一個訊息或文本的固定長度的值,它由一個單向Hash加密函式對訊息進行作用而產生
  • 使用數字摘要生成的值是不可以篡改的,為了保證檔案或者值的安全

1.3.1 特點

無論輸入的訊息有多長,計算出來的訊息摘要的長度總是固定的,例如應用MD5演算法摘要的訊息有128個位元位,用SHA-1演算法摘要的訊息最終有160位元位的輸出

只要輸入的訊息不同,對其進行摘要以后產生的摘要訊息也必不相同;但相同的輸入必會產生相同的輸出

訊息摘要是單向、不可逆的

常見演算法 :

- MD5
- SHA1
- SHA256
- SHA512

百度搜索 tomcat ,進入官網下載 ,會經常發現有 sha1,sha512 , 這些都是數字摘要

1.3.2 獲取字串訊息摘要

public class DigestDemo1 {

    public static void main(String[] args) throws Exception{
        // 原文
        String input = "aa";
        // 演算法
        String algorithm = "MD5";
        // 獲取數字摘要物件
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 獲取訊息數字摘要的位元組陣列
        byte[] digest = messageDigest.digest(input.getBytes());
        System.out.println(new String(digest));
    }
}

運行:

1.3.3 base64編碼

public class DigestDemo1 {

    public static void main(String[] args) throws Exception{
        // 原文
        String input = "aa";
        // 演算法
        String algorithm = "MD5";
        // 獲取數字摘要物件
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 訊息數字摘要
        byte[] digest = messageDigest.digest(input.getBytes());
//        System.out.println(new String(digest));
        // base64編碼
        System.out.println(Base64.encode(digest));
    }
}

運行結果:

這里還需要注意一點,數字摘要一般是十六進制的,所以我們在base64轉碼格式的基礎上再轉成16進制,

public class DigestDemo1 {

    public static void main(String[] args) throws Exception{
        // 4124bc0a9335c27f086f24ba207a4912     md5 在線校驗
        // QSS8CpM1wn8IbyS6IHpJEg==             訊息摘要使用的是16進制
        // 原文
        String input = "aa";
        // 演算法
        String algorithm = "MD5";
        // 獲取數字摘要物件
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 訊息數字摘要
        byte[] digest = messageDigest.digest(input.getBytes());
//        System.out.println(new String(digest));
        // base64編碼
//        System.out.println(Base64.encode(digest));
        // 創建物件用來拼接
        StringBuilder sb = new StringBuilder();

        for (byte b : digest) {
            // 轉成 16進制
            String s = Integer.toHexString(b & 0xff);
            //System.out.println(s);
            if (s.length() == 1){
                // 如果生成的字符只有一個,前面補0
                s = "0"+s;
            }
            sb.append(s);
        }
        System.out.println(sb.toString());
        
    }
}

1.3.4 其他數字摘要演算法

public class DigestDemo1 {

    public static void main(String[] args) throws Exception{
        // 4124bc0a9335c27f086f24ba207a4912     md5 在線校驗
        // QSS8CpM1wn8IbyS6IHpJEg==             訊息摘要使用的是16進制
        // 原文
        String input = "aa";
        // 演算法
        String algorithm = "MD5";
        // 獲取數字摘要物件
        String md5 = getDigest(input, "MD5");
        System.out.println(md5);

        String sha1 = getDigest(input, "SHA-1");
        System.out.println(sha1);

        String sha256 = getDigest(input, "SHA-256");
        System.out.println(sha256);

        String sha512 = getDigest(input, "SHA-512");
        System.out.println(sha512);


    }

    private static String toHex(byte[] digest) throws Exception {

//        System.out.println(new String(digest));
        // base64編碼
//        System.out.println(Base64.encode(digest));
        // 創建物件用來拼接
        StringBuilder sb = new StringBuilder();

        for (byte b : digest) {
            // 轉成 16進制
            String s = Integer.toHexString(b & 0xff);
            if (s.length() == 1){
                // 如果生成的字符只有一個,前面補0
                s = "0"+s;
            }
            sb.append(s);
        }
        System.out.println("16進制資料的長度:" + sb.toString().getBytes().length);
        return sb.toString();
    }

    private static String getDigest(String input, String algorithm) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 訊息數字摘要
        byte[] digest = messageDigest.digest(input.getBytes());
        System.out.println("密文的位元組長度:" + digest.length);

        return toHex(digest);
    }
}

運行結果:

1.3.5 獲取檔案訊息摘要

public class DigestDemo {

    public static void main(String[] args) throws Exception{
        String input = "aa";
        String algorithm = "MD5";

        // sha1 可以實作秒傳功能

        String sha1 = getDigestFile("apache-tomcat-9.0.10-windows-x64.zip", "SHA-1");
        System.out.println(sha1);

        String sha512 = getDigestFile("apache-tomcat-9.0.10-windows-x64.zip", "SHA-512");
        System.out.println(sha512);

        String md5 = getDigest("aa", "MD5");
        System.out.println(md5);

        String md51 = getDigest("aa ", "MD5");
        System.out.println(md51);
    }

    private static String getDigestFile(String filePath, String algorithm) throws Exception{
        FileInputStream fis = new FileInputStream(filePath);
        int len;
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while ( (len =  fis.read(buffer))!=-1){
            baos.write(buffer,0,len);
        }
        // 獲取訊息摘要物件
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        // 獲取訊息摘要
        byte[] digest = messageDigest.digest(baos.toByteArray());
        System.out.println("密文的位元組長度:"+digest.length);
        return toHex(digest);
    }

    private static String getDigest(String input, String algorithm) throws Exception{
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        byte[] digest = messageDigest.digest(input.getBytes());
        System.out.println("密文的位元組長度:"+digest.length);
        return toHex(digest);
    }

    private static String toHex(byte[] digest) {
        //        System.out.println(new String(digest));
        // 訊息摘要進行表示的時候,是用16進制進行表示
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            // 轉成16進制

            String s = Integer.toHexString(b & 0xff);
            // 保持資料的完整性,前面不夠的用0補齊
            if (s.length()==1){
                s="0"+s;
            }
            sb.append(s);
        }
        System.out.println("16進制資料的長度:"+ sb.toString().getBytes().length);
        return sb.toString();
    }
}

運行程式 ,獲取 sha-1 和 sha-512 的值:

查看 tomcat 官網上面 sha-1 和 sha-512 的值:

使用 sha-1 演算法,可以實作秒傳功能,不管咱們如何修改檔案的名字,最后得到的值是一樣的

總結:

  • MD5演算法 : 摘要結果16個位元組, 轉16進制后32個位元組
  • SHA1演算法 : 摘要結果20個位元組, 轉16進制后40個位元組
  • SHA256演算法 : 摘要結果32個位元組, 轉16進制后64個位元組
  • SHA512演算法 : 摘要結果64個位元組, 轉16進制后128個位元組

1.4 非對稱加密

簡介:

① 非對稱加密演算法又稱現代加密演算法,

② 非對稱加密是計算機通信安全的基石,保證了加密資料不會被破解,

③ 與對稱加密演算法不同,非對稱加密演算法需要兩個密鑰:公開密鑰(publickey) 和私有密(privatekey)

④ 公開密鑰和私有密鑰是一對

⑤ 如果用公開密鑰對資料進行加密,只有用對應的私有密鑰才能解密,

⑥ 如果用私有密鑰對資料進行加密,只有用對應的公開密鑰才能解密,

⑦ 因為加密和解密使用的是兩個不同的密鑰,所以這種演算法叫作非對稱加密演算法,

示例:

  • 首先生成密鑰對, 公鑰為(5,14), 私鑰為(11,14)
  • 現在A希望將原文2發送給B
  • A使用公鑰加密資料. 2的5次方mod 14 = 4 , 將密文4發送給B
  • B使用私鑰解密資料. 4的11次方mod14 = 2, 得到原文2
    特點:
  • 加密和解密使用不同的密鑰
  • 如果使用私鑰加密, 只能使用公鑰解密
  • 如果使用公鑰加密, 只能使用私鑰解密
  • 處理資料的速度較慢, 因為安全級別高
    常見演算法:
  • RSA
  • ECC

1.4.1 生成公鑰和私鑰

public class RSAdemo {
    public static void main(String[] args) throws Exception {
      
        // 加密演算法
        String algorithm = "RSA";
        //  創建密鑰對生成器物件
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私鑰
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公鑰
        PublicKey publicKey = keyPair.getPublic();
        // 獲取私鑰位元組陣列
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 獲取公鑰位元組陣列
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 對公私鑰進行base64編碼
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);
        // 列印私鑰
        System.out.println(privateKeyString);
        // 列印公鑰
        System.out.println(publicKeyString);
    }
}

運行程式:先列印的是私鑰 , 后面列印的是公鑰,

1.4.2 私鑰加密

public class RSAdemo {
    public static void main(String[] args) throws Exception {
        String input = "硅谷";
        // 加密演算法
        String algorithm = "RSA";
        //  創建密鑰對生成器物件
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私鑰
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公鑰
        PublicKey publicKey = keyPair.getPublic();
        // 獲取私鑰位元組陣列
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 獲取公鑰位元組陣列
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 對公私鑰進行base64編碼
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);


        // 創建加密物件
        // 引數表示加密演算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一個引數:加密的模式
        // 第二個引數:使用私鑰進行加密
        cipher.init(Cipher.ENCRYPT_MODE,privateKey);
        // 私鑰加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        System.out.println(Base64.encode(bytes));
       
    }
}

運行結果:

1.4.3 私鑰加密私鑰解密

public class RSAdemo {
    public static void main(String[] args) throws Exception {
        String input = "硅谷";
        // 加密演算法
        String algorithm = "RSA";
        //  創建密鑰對生成器物件
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私鑰
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公鑰
        PublicKey publicKey = keyPair.getPublic();
        // 獲取私鑰位元組陣列
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 獲取公鑰位元組陣列
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 對公私鑰進行base64編碼
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);


        // 創建加密物件
        // 引數表示加密演算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一個引數:加密的模式
        // 第二個引數:使用私鑰進行加密
        cipher.init(Cipher.ENCRYPT_MODE,privateKey);
        // 私鑰加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        System.out.println(Base64.encode(bytes));
        // 私鑰進行解密
        cipher.init(Cipher.DECRYPT_MODE,publicKey);
        // 對密文進行解密,不需要使用base64,因為原文不會亂碼
        byte[] bytes1 = cipher.doFinal(bytes);
        System.out.println(new String(bytes1));

    }
}

運行程式 ,因為私鑰加密,只能公鑰解密:

1.4.4 私鑰加密公鑰解密

public class RSAdemo {
    public static void main(String[] args) throws Exception {
        String input = "硅谷";
        // 加密演算法
        String algorithm = "RSA";
        //  創建密鑰對生成器物件
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密鑰對
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私鑰
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公鑰
        PublicKey publicKey = keyPair.getPublic();
        // 獲取私鑰位元組陣列
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 獲取公鑰位元組陣列
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 對公私鑰進行base64編碼
        String privateKeyString = Base64.encode(privateKeyEncoded);
        String publicKeyString = Base64.encode(publicKeyEncoded);


        // 創建加密物件
        // 引數表示加密演算法
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化加密
        // 第一個引數:加密的模式
        // 第二個引數:使用私鑰進行加密
        cipher.init(Cipher.ENCRYPT_MODE,privateKey);
        // 私鑰加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        System.out.println(Base64.encode(bytes));
        // 私鑰進行解密
        cipher.init(Cipher.DECRYPT_MODE,publicKey);
        // 對密文進行解密,不需要使用base64,因為原文不會亂碼
        byte[] bytes1 = cipher.doFinal(bytes);
        System.out.println(new String(bytes1));

    }
}

運行程式:

1.5 數字簽名

數字簽名(又稱公鑰數字簽名)是只有資訊的發送者才能產生的別人無法偽造的一段數字串,這段數字串同時也是對資訊的發送者發送資訊真實性的一個有效證明,它是一種類似寫在紙上的普通的物理簽名,但是使用了公鑰加密領域的技術來實作的,用于鑒別數字資訊的方法,一套數字簽名通常定義兩種互補的運算,一個用于簽名,另一個用于驗證,數字簽名是非對稱密鑰加密技術與數字摘要技術的應用,

1.5.1 簡單認識

相信我們都寫過信,在寫信的時候落款處總是要留下自己的名字,用來表示寫信的人是誰,我們簽的這個字就是生活中的簽名,
而數字簽名呢?其實也是同樣的道理,他的含義是:在網路中傳輸資料時候,給資料添加一個數字簽名,表示是誰發的資料,而且還能證明資料沒有被篡改,

OK,數字簽名的主要作用就是保證了資料的有效性(驗證是誰發的)和完整性(證明資訊沒有被篡改),下面我們就來好好地看一下他的底層實作原理是什么樣子的,

1.5.2 基本原理

為了理解得清楚,我們通過案例一步一步來講解,話說張三有倆好哥們A、B,由于作業原因,張三和AB寫郵件的時候為了安全都需要加密,于是張三想到了數字簽名:

整個思路是這個樣子的:

第一步:加密采用非對稱加密,張三有三把鑰匙,兩把公鑰,送給朋友,一把私鑰留給自己,

第二步:A或者B寫郵件給張三:A先用公鑰對郵件加密,然后張三收到郵件之后使用私鑰解密,

第三步:張三寫郵件給A或者B:

(1)張三寫完郵件,先用hash函式生成郵件的摘要,附著在文章上面,這就完成了數字簽名,然后張三再使用私鑰加密,就可以把郵件發出去了,

(2)A或者是B收到郵件之后,先把數字簽名取下來,然后使用自己的公鑰解密即可,這時候取下來的數字簽名中的摘要若和張三的一致,那就認為是張三發來的,再對信件本身使用Hash函式,將得到的結果,與上一步得到的摘要進行對比,如果兩者一致,就證明這封信未被修改過,

上面的流程我們使用一張圖來演示一下:

首先把公鑰送給朋友A和B:

還有就是最后一個比較麻煩的,張三給A或者B發郵件:

1.5.3 數字證書

上面提到我們對簽名進行驗證時,需要用到公鑰,如果公鑰是偽造的,那我們無法驗證數字簽名了,也就根本不可能從數字簽名確定對方的合法性了,這時候證書就閃亮登場了,我們可能都有考各種證書的經歷,比如說普通話證書,四六級證書等等,但是歸根結底,到任何場合我們都能拿出我們的證書來證明自己確實已經考過了普通話,考過了四六級,這里的證書也是同樣的道理,

如果不理解證書的作用,我們可以舉一個例子,比如說我們的畢業證書,任何公司都會承認,為什么會承認?因為那是國家發得,大家都信任國家,也就是說只要是國家的認證機構,我們都信任它是合法的,

那么這個證書是如何生成的呢?我們再來看一張圖:

此時即使張三的朋友A把公鑰弄錯了,張三也可以通過這個證書驗證,

1.5.4 代碼實作

import java.security.*;
import com.sun.org.apache.xml.internal.security.utils.Base64;
public class SignatureDemo {
    public static void main(String[] args) throws Exception {
        String a = "123";

        PublicKey publicKey = RsaDemo.loadPublicKeyFromFile("RSA", "a.pub");
        PrivateKey privateKey = RsaDemo.loadPrivateKeyFromFile("RSA", "a.pri");

        String signaturedData = https://www.cnblogs.com/xhj928675426/p/getSignature(a, "sha256withrsa", privateKey);

        boolean b = verifySignature(a, "sha256withrsa", publicKey, signaturedData);

    }

    /**
     * 生成簽名
     *
     * @param input      : 原文
     * @param algorithm  : 演算法
     * @param privateKey : 私鑰
     * @return : 簽名
     * @throws Exception
     */
    private static String getSignature(String input, String algorithm, PrivateKey privateKey) throws Exception {
        // 獲取簽名物件
        Signature signature = Signature.getInstance(algorithm);
        // 初始化簽名
        signature.initSign(privateKey);
        // 傳入原文
        signature.update(input.getBytes());
        // 開始簽名
        byte[] sign = signature.sign();
        // 對簽名資料進行Base64編碼
        return Base64.encode(sign);
    }

    /**
     * 校驗簽名
     *
     * @param input          : 原文
     * @param algorithm      : 演算法
     * @param publicKey      : 公鑰
     * @param signaturedData : 簽名
     * @return : 資料是否被篡改
     * @throws Exception
     */
    private static boolean verifySignature(String input, String algorithm, PublicKey publicKey, String signaturedData) throws Exception {
        // 獲取簽名物件
        Signature signature = Signature.getInstance(algorithm);
        // 初始化簽名
        signature.initVerify(publicKey);
        // 傳入原文
        signature.update(input.getBytes());
        // 校驗資料
        return signature.verify(Base64.decode(signaturedData));

    }

}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/628.html

標籤:區塊鏈

上一篇:密碼學DAY1_02

下一篇:NTP時鐘服務器的特點(京準電子)

標籤雲
其他(123570) Java(13369) Python(12729) C(7542) 區塊鏈(7372) JavaScript(7048) 基礎類(6313) AI(6244) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4120) MySQL(4012) Linux(3394) C語言(3288) C++語言(3117) Java相關(2746) 疑難問題(2699) 單片機工控(2479) Web開發(1951) 網絡通信(1793) 數據庫相關(1767) VB基礎類(1755) PHP(1727) 開發(1646) 系統維護與使用區(1617) .NETCore(1586) 基礎和管理(1579) JavaEE(1566) C++(1527) 專題技術討論區(1515) Windows客戶端使用(1484) HtmlCss(1466) ASP.NET(1428) Unity3D(1354) VCL組件開發及應用(1353) HTML(CSS)(1220) 其他技術討論專區(1200) WindowsServer(1192) .NET技术(1165) 交換及路由技術(1149) 語言基礎算法系統設計(1133) WindowsSDKAPI(1124) 界面(1088) JavaSE(1075) Qt(1074) VBA(1048) 新手樂園(1016) 其他開發語言(947) Go(907) HTML5(901) 新技術前沿(898) 硬件設計(872) 區塊鏈技術(860) 網絡編程(857) 非技術版(846) 一般軟件使用(839) 網絡協議與配置(835) Eclipse(790) Spark(750) 下載資源懸賞專區(743)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • 具有多個成員函式的實體的執行緒安全鎖定

    我有一個被多個執行緒使用的結構實體。每個執行緒都包含未知數量的函式呼叫,這些函式呼叫會改變結構體成員變數。我有一個專用函式,它嘗試為當前執行緒“保留”結構實體,并且我...

    uj5u.com 2021-10-16 16:32:53 more
  • 如何避免沒有謂詞的虛假喚醒?

    我有一個執行緒可以叫它 t1,它會在 x 秒后定期發送一些東西。這個“x 秒部分”可以從其他執行緒 (t2)更改。我應該能夠從執行緒 t1 執行以下操作。等待“x 秒”然后發送一些...

    uj5u.com 2021-10-16 16:32:27 more
  • 多次啟動執行緒

    我想使用執行緒將檔案上傳到服務器。只要ThreadState是Unstarted,我就可以用它ThreadName.Start()來啟動執行緒。代碼完成后ThreadState會得到Stopped。我怎樣才能再次啟動該...

    uj5u.com 2021-10-16 16:31:50 more
  • 多執行緒中的Boost:asio和async

    我需要呼叫作為遠程服務器請求的方法。之后我想等待答案,并且等待不會被其他異步函式/物件(例如計時器)阻止。方法 got_response(...) 告訴用戶他從遠程服務器得到了一個答案,方...

    uj5u.com 2021-10-16 16:31:18 more
  • 為什么從并發佇列異步呼叫`DispatchQueue.main.sync`成功但同步

    在這里,我創建了具有 .background 優先級的并發佇列:let background = DispatchQueue(label: "backgroundQueue", qos: .background,...

    uj5u.com 2021-10-16 16:30:33 more
  • 如果執行緒生成速度過快,Ruby作業分配會失敗

    前幾天我遇到了一個問題,我花了 2 個小時在錯誤的地方尋找答案。在此程序中,我將代碼精簡為以下版本。只要我sleep(0.1)在回圈中創建執行緒,這里的執行緒就可以作業。如果省略...

    uj5u.com 2021-10-16 16:29:58 more
  • 使用多處理python將元素添加到串列

    我定義了一個接受單個整數輸入并回傳輸出整數的函式。def get_output(n): output = # process the integer return output現在我已經定義了一個必須使用上面定義的函式進...

    uj5u.com 2021-10-16 16:29:29 more
  • 為什么Javascript的阻塞函式比Python少得多

    從 Javascript 到 Python,看著asyncio讓我有點困惑。作為對并發基本概念不熟悉的人,我只是假設對 Javascript 并發有一個膚淺的理解。async / await在 Javascript 中使用的基...

    uj5u.com 2021-10-16 16:28:37 more
  • 如何從回復id(Python)中獲取執行緒/對話?

    我是 python 的相對新手,我正在嘗試從具有 ID 串列的資料幀重建對話/執行緒。我目前有一個推文/reddit帖子的pandas資料框,其格式大致如下:ID文本parent_id回復編號1呸呸_ 郵政...

    uj5u.com 2021-10-16 16:28:09 more
  • 將函式傳遞給多處理池中的地圖或星圖

    我一直試圖在我的機器上的 Jupyter 上測驗這段簡單的代碼,并且該單元無限期地運行而不輸出任何內容。是否有某種錯誤或什么?我為熊貓行程使用了??完全相同的代碼,pool.map并且...

    uj5u.com 2021-10-16 16:27:40 more