38_安全密码学基础

这篇具有很好参考价值的文章主要介绍了38_安全密码学基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

安全密码学

在了解安全密码学之前,我们需要补充一些额外知识。

ASCII

是基于拉丁字母的一套电脑编码系统,就好像这些字符,对应的就是十进制的65 97,简单来说就是计算机没有办法识别字符,他只理解01二进制,所以用一个字符表,规定了什么字符用什么01表示。

   @Test
    public void ascii() {
       char c1 = 'A';
       char c2 = 'a';

        System.out.println((byte)c1);
        System.out.println((byte)c2);

        //65 
        //97
    }
  @Test
    public void ascii() {
        char c1 = 'A';
        char c2 = 'a';
		
        // 字符 = 整型 无强转可替换
        int n1 = c1;
        int n2 = c2;
        System.out.println("---将字符转为十进制的ASCII码--");
        System.out.println(n1);
        System.out.println(n2);


        System.out.println("---将字符转为二进制的ASCII码--");
        String binary1 = Integer.toBinaryString(n1);
        String binary2 = Integer.toBinaryString(n2);
        System.out.println(binary1);
        System.out.println(binary2);

        /**
         *
         * ---将字符转为十进制的ASCII码--
         * 65
         * 97
         * ---将字符转为二进制的ASCII码--
         * 1000001
         * 1100001
         *
         */

    }

PBE

PBE(Password Based Encryption,基于口令加密)算法是一种基于口令的加密算法,其特点在于口令是由用户自己掌握的,采用随机数杂凑多重加密等方法保证数据的安全性, PBE算法没有密钥的概念,密钥在其它对称加密算法中是经过算法计算得出来的,PBE算法则是使用口令替代了密钥。

PKCS&X.509

ASN.1

在计算机界,有各种密码学标准,它们表示了如何在计算机中计算、存储、传输(等)各种算法,这些标准由 IEFT、ITU-T、ISO 等标准组织机构编写。

ASN.1(Abstract Syntax Notation One) 是 ISO 和 ITU-T 的联合标准,是描述数据的表示、编码、传输、解码的灵活的记法。它提供了一套正式、无歧义和精确的规则以描述独立于特定计算机硬件的对象结构。

ASN.1 本身只定义了表示信息的抽象句法,但是没有限定其编码的方法**。各种 ASN.1 编码规则提供了由 ASN.1 描述其抽象句法的数据的值的传送语法(具体表达)。标准的 ASN.1 编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、可分辨编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和 XML 编码规则(XER,XML Encoding Rules)。

该机构从上层规定了规范,有点像IP协议ISO组织一个意思。

  • X.509

X.509 是密码学里公钥证书的格式标准。X.509 证书已应用包括 TLS/SSL 在内的众多网络协议里和一些非在线应用场景里,比如电子签名服务。X.509 证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等、 签名信息(可以是证书签发机构 CA 的签名,也可以是自签名)

  • PKCS 系列

公钥加密标准(Public Key Cryptography Standards, PKCS),此一标准的设计与发布皆由 RSA 资讯安全公司(英语:RSA Security)所制定。

标准 版本 名称 简介
PKCS #1 2.2 RSA 加密规范(RSA Cryptography Standard) 提供了基于 RSA 算法的公钥加密实现的建议,包括加密原语、加密方案、带附录的签名方案,以及用于表示密钥和识别方案的 ASN.1 语法。参见 RFC 8017。
PKCS #2 - 弃用 原本是用以规范 RSA 加密摘要的转换方式,现已被纳入 PKCS #1 之中。
PKCS #3 1.4 Diffie-Hellman 协议标准(Diffie-Hellman key agreement Standard) 规范以 Diffie-Hellman 协议为基础的密钥协议标准。其功能可以让两方通过过协议,拟定一把会议密钥(Session key)。
PKCS #4 - 弃用 原本用以规范转换 RSA 密钥的流程。已被纳入 PKCS #1 之中。
PKCS #5 2.1 基于密码的加密规范(Password-based Encryption Standard) 参见 RFC 8018。
PKCS #6 1.5 证书扩展语法标准(Extended-Certificate Syntax Standard) 将原本 X.509 的证书格式标准加以扩充。
PKCS #7 1.5 密码讯息语法标准(Cryptographic Message Syntax Standard) 参见 RFC 2315。规范了以公开密钥基础设施(PKI)所产生之签章/密文的格式。其目的一样是为了拓展数位证书的应用。其中,包含了 S/MIME 与 CMS(英语:Cryptographic Message Syntax)。
PKCS #8 1.2 私钥信息语法规范(Private-Key Information Syntax Standard) 存储私钥信息的标准语法。参见 RFC 5208。
PKCS #9 2.0 选择属性格式(Selected Attribute Types) 定义 PKCS #6、7、8、10 的选择属性格式。
PKCS #10 1.7 证书申请标准(Certification Request Standard) 参见 RFC 2986。规范了向证书中心申请证书的 CSR(certificate signing request)的格式。
PKCS #11 2.20 密码装置标准介面(Cryptographic Token Interface (Cryptoki)) 定义了密码装置的应用程式介面(API)之规格。
PKCS #12 1.0 个人讯息交换标准(Personal Information Exchange Syntax Standard) 定义了包含私钥与公钥证书(public key certificate)的文件格式。私钥采密码(password)保护。常见的 PFX 就履行了 PKCS #12。
PKCS #13 椭圆曲线密码学标准(Elliptic curve cryptography Standard) 制定中。规范以椭圆曲线密码学为基础所发展之密码技术应用。椭圆曲线密码学是新的密码学技术,其强度与效率皆比现行以指数运算为基础之密码学演算法来的优秀。然而,该演算法的应用尚不普及。
PKCS #14 伪随机数生成器(英语:Pseudorandom number generator)标准 制定中。规范伪随机数生成器的使用与设计。
PKCS #15 1.1 密码装置讯息格式标准(Cryptographic Token Information Format Standard) 定义了密码设备内部数据的组织结构。

Base64

Base64只是更利于数据显示,并不具备加密效果。

  • 能表示的全部字符

因为Base64编码会把字节按照6bit 为一组进行划分,而6位所表示的二进制数的范围就是 000000 ~ 111111

能表示的字符如下所示:

38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java

  • 编码过程

他会把客户端的字符按照 3个字节 为一组进行编码。如果客户端字符不够不够三个字节,他内部会用0进行补位。补齐到3个字节一组。

对于一组来说,他会按照6bit 进行二次分组。分成4组。

这4组,每一组就能表示一个字符

请注意,如果是补位得到的组,也就是000000 表示的不是ASCII码里面的A字符,而是 = 。

38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java

Java内置了Base64类,封装了编码解码的算法,帮我们做上面这些事情。

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64Test {

    @Test
    @DisplayName("将字符串转为Base64编码的字符串")
    public void strToBase64(){
        String source = "123456789";
        Base64.Encoder encoder = Base64.getEncoder();
        String base64 = encoder.encodeToString(source.getBytes(StandardCharsets.UTF_8));
        System.out.println(base64); // MTIzNDU2Nzg5
    }

    @Test
    @DisplayName("将Base64编码的字符串转为字符串")
    public void base64ToStr(){
        String base64 = "MTIzNDU2Nzg5";
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] decode = decoder.decode(base64);
        String source = new String(decode);
        System.out.println(source); //123456789
    }
}

签名

签名的优点:

A向B发送签名的消息P,可以有如下好处:

  • 1、B可以验证消息P确实来源A
  • 2、A以后不能否定发送过P
  • 3、B不能编造或者改变消息P

如商城A发送消息P给支付宝网关B

从支付宝网关的角度看:

从互联网环境中,拿到了A的消息,通过验签(解密出来的数据和发送数据是否一致)来确定数据传输过程中没有被他人利用篡改。

从而执行了转账业务操作。

从商城A的角度看:

发送的数据签名是用了自己的私钥签名的,还用了支付宝的公钥加密了。很安全。支付宝不能改变这个消息。

38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java

摘要

摘要算法:SHA和MD5:就是通过一种算法,依据数据内容生成一种固定长度的摘要,这串摘要值与原数据存在对应关系。

实际应用过程中,因为需要加密的数据可能会很大,进行加密费时费力,所以一般都会把原数据先进行摘要,然后对这个摘要值进行加密,将原数据的明文和加密后的摘要值一起传给你.这样你解开加密后的摘要值,再和你得到的数据进行的摘要值对应一下就可以知道数据有没有被修改了(下文说的签名)。

摘要算法有很多,来看看JDK支持的摘要算法,摘要算法又分两种实现

一种是 MessageDigest 消息摘要

另一种是 Mac Mac实现

MessageDigest

我先来看看MessageDigest 实现的。

MD2

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {

    @Test
    @DisplayName("MD2 ")
    public void encAndDen() throws NoSuchAlgorithmException {
        String  algorithm = "MD2";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // 1FQSULWGKW/M5d6kRjrhfw==

    }

}
package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {

    @Test
    @DisplayName("MD5 加密")
    public void jdkMd5AndEncodeTOBase64() throws NoSuchAlgorithmException {
        String  algorithm = "MD5";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // 4QrcOUm6Wau+VuBX8g+IPg==

    }
}

MD5 可以将任意长度的原文 生成一个 128位(16字节的哈希值)。

在某些业务场景,我们除了会把该16字节的哈希值 转为 Base64 字符串 之外,也可以处理成 16进制字符串。

package com.wnx.naizi;

import cn.hutool.core.util.HexUtil;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class CipherTest {


    @Test
    @DisplayName("MD5 加密")
    public void jdkMd5AndEncodeTOHexStr() throws NoSuchAlgorithmException {
        String  algorithm = "MD5";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        String s = HexUtil.encodeHexStr(digest);
        System.out.println(s);     //

    }
}

SHA-1

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {



    @Test
    @DisplayName("SHA-1 摘要")
    public void encAndDen() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-1";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        System.out.println(digest.length); // 20
        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // fEqNCco3Yq9h5ZUglD3CZJT4lBs=

    }

}
package com.wnx.naizi;

import cn.hutool.core.util.HexUtil;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class CipherTest {


    @Test
    @DisplayName("SHA-1 摘要")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-1";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        String str = HexUtil.encodeHexStr(digest);  // 7c4a8d09ca3762af61e59520943dc26494f8941b
        System.out.println(str);


    }
}

SHA-1可以将任意长度的原文 生成 20个字节(20 * 8 bit = 160 bit)位的哈希值。

我们也会把这样的Hash值转为Base64编码字符串之外,有时业务上也会转为 十六进制字符串。

SHA-224

package com.wnx.naizi;

import cn.hutool.core.util.HexUtil;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class CipherTest {


    @Test
    @DisplayName("SHA-224 摘要")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-224";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        String str = HexUtil.encodeHexStr(digest);  // f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6
        System.out.println(str);

    }
}

SHA-256

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {

    @Test
    @DisplayName("SHA-256 摘要")
    public void encAndDen() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-256";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // jZae727K08KaOmKSgOaGzww/XVqGr/PKEgIMkjrcbJI=

    }

}

SHA-384

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {

    @Test
    @DisplayName("SHA-384 加密")
    public void encAndDen() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-384";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // CpievEp3tWpuK7exnZldGFzkQJDBPimEt+zG1EbUth6pmRt2pMLwSxtNJEhBRJRU

    }
}

SHA-512

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class CipherTest {

    @Test
    @DisplayName("SHA-512 加密")
    public void encAndDen() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-512";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String result = Base64.getEncoder().encodeToString(digest);
        System.out.println(result);     // ujJTh2rta8ItSm/1PYQGxq2GQZXtFEq1yHYhtsIztUi66uaVbfNG7IwX9eoQ817jy8UUeX7X3dMUVGTioLq0Ew==

    }

}

SHA-512/224

    @Test
    @DisplayName("SHA-512/224 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-512/224";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        String str = HexUtil.encodeHexStr(digest);  // 007ca663c61310fbee4c1680a5bbe70071825079b23f092713383296
        System.out.println(str);


    }

SHA-512/256

    @Test
    @DisplayName("SHA-512/256 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA-512/256";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));
        String str = HexUtil.encodeHexStr(digest);  // 184b5379d5b5a7ab42d3de1d0ca1fedc1f0ffb14a7673ebd026a6369745deb72
        System.out.println(str);


    }

SHA3-224


    @Test
    @DisplayName("SHA3-224 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA3-224";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String str = new BigInteger(1, digest).toString(16);    // 6be790258b73da9441099c4cb6aeec1f0c883152dd74e7581b70a648
        System.out.println(str);


    }

SHA3-256

    @Test
    @DisplayName("SHA3-256 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA3-256";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String str = new BigInteger(1, digest).toString(16);    // d7190eb194ff9494625514b6d178c87f99c5973e28c398969d2233f2960a573e
        System.out.println(str);


    }

SHA3-384

    @Test
    @DisplayName("SHA3-384 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA3-384";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String str = new BigInteger(1, digest).toString(16);    // 1fb0da774034ba308fbe02f3e90dc004191df7aec3758b6be8451d09f1ff7ec18765f96e71faff637925c6be1d65f1cd
        System.out.println(str);


    }

SHA3-512

    @Test
    @DisplayName("SHA3-512 加密")
    public void encAndDenToHexString() throws NoSuchAlgorithmException {
        String  algorithm = "SHA3-512";
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        String source = "123456";
        byte[] digest = messageDigest.digest(source.getBytes(StandardCharsets.UTF_8));

        String str = new BigInteger(1, digest).toString(16);    //64d09d9930c8ecf79e513167a588cb75439b762ce8f9b22ea59765f32aa74ca19d2f1e97dc922a3d4954594a05062917fb24d1f8e72f2ed02a58ed7534f94d27
        System.out.println(str);


    }

Mac

MessageDigest 比较。这个Mac对象需要一个SecretKey 进行初始化,才能用。

HmacMD5

    @Test
    @DisplayName("HmacMD5 加密")
    public void jdkMd5AndEncodeTOBase64() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacMD5";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 2fa5a2a2d2e9d68a2cfb9821e2415464

    }

HmacSHA1

public class CipherTest {



    @Test
    @DisplayName("HmacSHA1 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA1";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 560462b95eff73ca176032de405c0c08297de10f

    }
 }

HmacSHA256

    @Test
    @DisplayName("HmacSHA256 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA256";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 8ad6f4abeb59ba6009724395c90049105b427050c10808618ebb9be4f9a33aa

    }

HmacSHA224

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA224 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA224";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 4cd1c941009fae2ac26587cc2cdaabe5c3a0f798f01fb618288aedf0

    }

}

HmacSHA384

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA384 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA384";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // a107a03e92e770c79d4d0e76160d853d63f253d4cc28654d39f03c0b8f900ea110b791dd9f67567ac3ed85f4692748d6

    }


}

HmacSHA512

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA512 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA512";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 4e646209bd3a2aab053efdaeb58300ebb1bb80c6c5c66640218bd0136b6faa051ef5e8834531d51f4f413bc1e439d72bd52b40292674d3381aeccbc030d912e2

    }



}

HmacSHA512/224

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA512/224 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA512/224";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // ee9f2b8c40fdded9f753b4816db7c308252726f14618c7b77573218a

    }

}

HmacSHA512/256

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA512/256 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA512/256";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 421dd7a2b5df6a6deac04da3f087a0a842ea77da07db58a65097a22fa616dfb5

    }

}

HmacSHA3-224

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA3-224 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA3-224";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 82889d40ef2964e42efb2bbb7ef9e23e9353a1e9002d8059049819b4

    }



}

HmacSHA3-256

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA3-256 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA3-256";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 42646c3ebc0eb96d605cc6a0d181c25ac558ca3710bf4fd4971698367648fd84

    }

}

HmacSHA3-224

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA3-224 加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA3-224";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 82889d40ef2964e42efb2bbb7ef9e23e9353a1e9002d8059049819b4

    }



}

HmacSHA3-384

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA3-384加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA3-384";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // 742b2721109585685add7d0c0abf5b655c78d749d8a1e3b59527e8faa4e0c9d2b4ce53a71aec3ae58f6e9f93780b283c

    }

}

HmacSHA3-512

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class CipherTest {

    @Test
    @DisplayName("HmacSHA3-512加密")
    public void encAndDec() throws NoSuchAlgorithmException, InvalidKeyException {
        String useKey = "123456789";
        String algorithm = "HmacSHA3-512";
        SecretKey secretKey = new SecretKeySpec(useKey.getBytes(), algorithm);

        Mac mac = Mac.getInstance(algorithm);
        mac.init(secretKey);

        String source = "123456";
        mac.update(source.getBytes());
        byte[] result = mac.doFinal();

        String hexStr = new BigInteger(1, result).toString(16);
        System.out.println(hexStr);
        // b10de64a2b9cb26893448e676a65e14aeffbb98014b94361ed37430c983ee52ca99f20a8a9fc66834e56e59a7cf822bb50dfab4ae7abe2a4dfc7764ae65fbc1f

    }
}

签名

日常什么时候需要签名?确定这个东西和你有关,是你批准的,是你同意的。XXXX合同??签名技术也被运用到互联网领域,确定这个数据包是你的。这XXX合同不是伪造的,对你,对他都是一种保护。在Java中对签名这件事用Signature对象表示。我们只需要写入签名算法就能把他创建出来。

Signature signature = Signature.getInstance("MD5WithRSA");

initSign

签名实例,实际上就是用某个hash算法把IP数据报的数据部分(POST报文请求体)得到一个Hash值了。然后用私钥加密。这就完成了签名工作了。在Java你需要对签名进行初始化,等价于人家给你笔的过程。

以下演示了根据私钥初始化签名。

    
      private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAA...";
      private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFAAOCA...";

    @Test
    @DisplayName("根据私钥初始化签名对象")
    public void initSignByPriateKey() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
      
      String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5WithRSA");
        signature.initSign(privateKey);
      

    }


   @Test
    @DisplayName("根据 私钥和秘密随机对象 初始化签名对象")
    public void getSignatureByPrivateKeyAndSecureRandom() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5WithRSA");
        SecureRandom secureRandom = new SecureRandom();

        signature.initSign(privateKey,secureRandom);
        byte[] sign = signature.sign();


    }

sign

拿到笔了,签个名吧老哥。

    
    private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFA...";


    private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBig...";

    
    @Test
    @DisplayName("签名对象进行签名")
    public void getSignatureByPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5WithRSA");

        

        signature.initSign(privateKey);
        
         // 需要签名的数据 = POST请求体数据
        byte[] needSignatureData = "王乃醒".getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);
        
        byte[] sign = signature.sign();

        String signResult = Base64.getEncoder().encodeToString(sign);
        System.out.println(signResult);
        // 需要签名的数据
        byte[] needSignatureData = "王乃醒".getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);
        
 //Scbno/HT9YmNPbzC0S3Sk1Q+6UivEecjoAZ9loFbmmsJvOfwiXEF48naPNfX1dRNt4FRAagv4EDpc0jUSAZmKn0yYkG44leXBRNMp72pMnIrl138odSRDlG4OZCFxnot3OGWJiBVVK+dRi5Sqe3js+/5Y35sxoCOe0d4HNvyFkiR4PWT1CTA62Q7UDNfBv/lgA2UNtzGpEREZvDU86utVj3H9nOvy4oo/X5k9NhdDr3EVODw2/tajoQNWWKNITMAfpz8Gd/uQe/us34sXZk7tkIFDCkqpcTpOlibN+yoIQ8yEcw3cnDlWHSNVxMBWzUQd0l9qMGHhqQZv3mayajxQ6zpKT5B3k8/+DBCTsH3bmkqYTllt60X+mToMRv0ZFQr8JEw/ZZDVV/yyCd+eg2EIGnqNY5p9M+UVYuFteF/vVwrJ4SbCWEsgQ2MWJ2qD8fsh4C+xZydP1SPzG4ilO7+ltHaBGP07xR+rp5my5D3iNxV+7yP8Oa1RD7uzFpYR7v5


    }

initVerify

好了,开始在互联网传输了。人家即使把信息拦截了,因为没有你的公钥,完全看不懂这是什么。。。最终经过路由转发到你手上了。你有公钥,解密他.

    
    private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFA...";


    private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBig...";


    @Test
    @DisplayName("签名验证公钥")
    public void initVerify() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(publicKey);

    }

verify

怎么验签?无非把解密数据用发送方的hash算法做一次他做过的事情,由相同原文经过同一hash算法后最终得到的hash值均一致(hash算法特点),所以我们看这个签名和这个hash如果一致,我就认为这个签名没有被篡改。

Java封装好了,你只需要告诉我 相同原文是啥?该事例POST请求数据 = 王乃醒

        
    private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFA...";
    private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBig...";


    @Test
    @DisplayName("用公钥验证签名")
    public void getPublicKeyByRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(publicKey);
        String signResult = "Scbno/HT9YmNPbzC0S3Sk1Q+6UivEecjoAZ9loFbmmsJvOfwiXEF48naPNfX1dRNt4FRAagv4EDpc0jUSAZmKn0yYkG44leXBRNMp72pMnIrl138odSRDlG4OZCFxnot3OGWJiBVVK+dRi5Sqe3js+/5Y35sxoCOe0d4HNvyFkiR4PWT1CTA62Q7UDNfBv/lgA2UNtzGpEREZvDU86utVj3H9nOvy4oo/X5k9NhdDr3EVODw2/tajoQNWWKNITMAfpz8Gd/uQe/us34sXZk7tkIFDCkqpcTpOlibN+yoIQ8yEcw3cnDlWHSNVxMBWzUQd0l9qMGHhqQZv3mayajxQ6zpKT5B3k8/+DBCTsH3bmkqYTllt60X+mToMRv0ZFQr8JEw/ZZDVV/yyCd+eg2EIGnqNY5p9M+UVYuFteF/vVwrJ4SbCWEsgQ2MWJ2qD8fsh4C+xZydP1SPzG4ilO7+ltHaBGP07xR+rp5my5D3iNxV+7yP8Oa1RD7uzFpYR7v5";

        byte[] data = Base64.getDecoder().decode(signResult);
        //对王乃醒请求报文 做一次hash。
        byte[] needSignatureData = "王乃醒".getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);

        boolean verify = signature.verify(data);
        System.out.println(verify);  // true


    }

有了上面的API铺垫,我们来看看Java原生支持的签名算法,并执行一遍完整的流程。

MD5WithRSA

package com.wnx.naizi;

import cn.hutool.core.io.FileUtil;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @ClassName: SecretKeyFactoryTest
 * @Package: com.wnx.naizi
 * @Description: 密钥工厂 API测试
 * @Author: wangnaixing
 * @Create: 2022/12/18 - 16:40
 * @Version:v1.0
 */
public class SignatureTest {


    private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFAASCB..";

    private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFAAOCAY..";


    @Test
    @DisplayName("签名")
    public void signByMD5WithRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5WithRSA");

        

        signature.initSign(privateKey);
        byte[] needSignatureData = "王乃醒".getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);
        byte[] sign = signature.sign();

        String signResult = Base64.getEncoder().encodeToString(sign);
        System.out.println(signResult);
        //Scbno/HT9YmNPbzC0S3Sk1Q+6UivEecjoAZ9loFbmmsJvOfwiXEF48naPNfX1dRNt4FRAagv4EDpc0jUSAZmKn0yYkG44leXBRNMp72pMnIrl138odSRDlG4OZCFxnot3OGWJiBVVK+dRi5Sqe3js+/5Y35sxoCOe0d4HNvyFkiR4PWT1CTA62Q7UDNfBv/lgA2UNtzGpEREZvDU86utVj3H9nOvy4oo/X5k9NhdDr3EVODw2/tajoQNWWKNITMAfpz8Gd/uQe/us34sXZk7tkIFDCkqpcTpOlibN+yoIQ8yEcw3cnDlWHSNVxMBWzUQd0l9qMGHhqQZv3mayajxQ6zpKT5B3k8/+DBCTsH3bmkqYTllt60X+mToMRv0ZFQr8JEw/ZZDVV/yyCd+eg2EIGnqNY5p9M+UVYuFteF/vVwrJ4SbCWEsgQ2MWJ2qD8fsh4C+xZydP1SPzG4ilO7+ltHaBGP07xR+rp5my5D3iNxV+7yP8Oa1RD7uzFpYR7v5

    }


    @Test
    @DisplayName("得到签名和传输数据 开始验签~~")
    public void verifyByMD5WithRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(publicKey);
        String signResult = "Scbno/HT9YmNPbzC0S3Sk1Q+6UivEecjoAZ9loFbmmsJvOfwiXEF48naPNfX1dRNt4FRAagv4EDpc0jUSAZmKn0yYkG44leXBRNMp72pMnIrl138odSRDlG4OZCFxnot3OGWJiBVVK+dRi5Sqe3js+/5Y35sxoCOe0d4HNvyFkiR4PWT1CTA62Q7UDNfBv/lgA2UNtzGpEREZvDU86utVj3H9nOvy4oo/X5k9NhdDr3EVODw2/tajoQNWWKNITMAfpz8Gd/uQe/us34sXZk7tkIFDCkqpcTpOlibN+yoIQ8yEcw3cnDlWHSNVxMBWzUQd0l9qMGHhqQZv3mayajxQ6zpKT5B3k8/+DBCTsH3bmkqYTllt60X+mToMRv0ZFQr8JEw/ZZDVV/yyCd+eg2EIGnqNY5p9M+UVYuFteF/vVwrJ4SbCWEsgQ2MWJ2qD8fsh4C+xZydP1SPzG4ilO7+ltHaBGP07xR+rp5my5D3iNxV+7yP8Oa1RD7uzFpYR7v5";

        byte[] data = Base64.getDecoder().decode(signResult);
        byte[] needSignatureData = "王乃醒".getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);

        boolean verify = signature.verify(data);
        System.out.println(verify);  // true

    }
}

SHA256WithRSA

package com.wnx.naizi;

import cn.hutool.core.io.FileUtil;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @ClassName: SignatureTest
 * @Package: com.wnx.naizi
 * @Description:
 * @Author: wangnaixing
 * @Create: 2022/12/25 - 17:39
 * @Version:v1.0
 */
public class SignatureTest {

    private String privateKeyStr = "MIIG/AIBADANBgkqhkiG9w0BAQEFAASC...";

    private String publicKeyStr = "MIIBojANBgkqhkiG9w0BAQEFA...";




    @Test
    @DisplayName("签他")
    public void signSHA256WithRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Signature signature = Signature.getInstance("SHA256WithRSA");



        signature.initSign(privateKey);
        String plainText = "王乃醒";
        byte[] needSignatureData = plainText.getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);
        byte[] sign = signature.sign();

        String signResult = Base64.getEncoder().encodeToString(sign);
        System.out.println(signResult);
        //     tlp4x/DKD2pwWCJ8vaGQ1f3KPFvL2uV4/WNgQGjyP6qEGtFCjLispMd78SOePb2xBweMpX6ddnSGTwHaTinPfIAE79MK0ebCzm9jnRy+2o1VOb6bmX1TL8BocNRifEAclLOUdw8DTRx6vWpf5Es+vDyTyR+RbNa8Q9qgX56Ot7Q1+85ze+15idvcWRy4YnUdYhh06zJm4avYqln8+vy93fFp83dKGptdi7ei5sJq08QUgw1btz+t/4T39rsWSvk4FNUpuCDKXNIuPjSzTVKk7i1GJUwO5tM/INwmsJal0Ill8p7awOfZKReh+UHbpXxr/VyFi53G0/eNa4f9Q96ws7mviKUsZN445ITjCBx2gRhfPAz8k9s96OTTlqru9XEvZduk+mXyGI9zEeoJe4lIF2hiyX4I3ExAgRxbIOCUukaOdVyc1ylNYeJwt6TPbstjP1XjogqPKsTVz/Y6y2f3gIArYNF1t8ZOT6r6W5cqjvkEVpeYeHw3S1kC0EbDLL8/

    }


    @Test
    @DisplayName("验货")
    public void verifySHA256WithRSA() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        String algorithm = "RSA";
        byte[] encodedKey = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance("SHA256WithRSA");
        signature.initVerify(publicKey);
        String signResult = "tlp4x/DKD2pwWCJ8vaGQ1f3KPFvL2uV4/WNgQGjyP6qEGtFCjLispMd78SOePb2xBweMpX6ddnSGTwHaTinPfIAE79MK0ebCzm9jnRy+2o1VOb6bmX1TL8BocNRifEAclLOUdw8DTRx6vWpf5Es+vDyTyR+RbNa8Q9qgX56Ot7Q1+85ze+15idvcWRy4YnUdYhh06zJm4avYqln8+vy93fFp83dKGptdi7ei5sJq08QUgw1btz+t/4T39rsWSvk4FNUpuCDKXNIuPjSzTVKk7i1GJUwO5tM/INwmsJal0Ill8p7awOfZKReh+UHbpXxr/VyFi53G0/eNa4f9Q96ws7mviKUsZN445ITjCBx2gRhfPAz8k9s96OTTlqru9XEvZduk+mXyGI9zEeoJe4lIF2hiyX4I3ExAgRxbIOCUukaOdVyc1ylNYeJwt6TPbstjP1XjogqPKsTVz/Y6y2f3gIArYNF1t8ZOT6r6W5cqjvkEVpeYeHw3S1kC0EbDLL8/";

        byte[] data = Base64.getDecoder().decode(signResult);
        String plainText = "王乃醒";
        byte[] needSignatureData = plainText.getBytes(StandardCharsets.UTF_8);
        signature.update(needSignatureData);

        boolean verify = signature.verify(data);
        System.out.println(verify);  // true


    }

}

证书

证书文件存在多种格式保存在计算机中。

1. .p12 .pfx 二进制格式,同时包含证书和私钥,一般有密码保护。
2. .pem 文本格式,保存证书或者私钥
3. .crt 二进制格式或者文本格式,只保存证书
4. .jks 二进制格式,同时包含证书和私钥,一般有密码保护;jks是java的专属格式,它里面可以存储多张证书。
5. .der .cer 二进制格式,只保存证书,不保存密钥

秘钥库类型:

  • 1、JKS
  • 2、PKCS12 行业标准

现在让我们制作一个证书吧,JDK提供了KeyTool 工具,借助他,我们就能生成证书啦。

# 使用JDK的KeyTool工具 生成秘钥
# 给秘钥起一个别名 指定为 keystore01 
# 给秘钥库的类型 指定为 JKS,
# 给秘钥使用的算法 指定为 RSA 
# 给秘钥的长度 指定为 2048 bit 
# 给指定秘钥生成路径, 指定为 D盘 名称为 keystore01.p12文件中
# 给秘钥库访问的密码 指定为 wangnaixing
# 给秘钥有效期 指定为 3650

keytool -genkey -alias keystore01 -storetype JKS -keyalg RSA -keysize 2048 -keystore D:/keystore01.p12 -storepass wangnaixing -validity 3650

嗯嗯,我们再生成一个新的,行业标准的 PKCS12

# 使用JDKKeyTool工具 生成秘钥
# 给秘钥起一个别名 指定为 keystore02 
# 给秘钥库的类型 指定为 PKCS12,
# 给秘钥使用的算法 指定为 RSA 
# 给秘钥的长度 指定为 2048 bit 
# 给指定秘钥生成路径, 指定为 D盘 名称为 keystore02.p12文件中
# 给秘钥库访问的密码 指定为 wangnaixing
# 给秘钥有效期 指定为 3650

keytool -genkey -alias keystore02 -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore D:/keystore02.p12 -storepass wangnaixing -validity 3650

KeyStore

我们想把 keystore01.p12 keystore02.p12 加载到Java中。该怎么做呢?Java提供了keyStore类来给我们做。

根据秘钥类型拿到KeyStore对象,load一下就好。这是不是很像Properties配置文件加载进Java中一样。

    @Test
    @DisplayName("获取密钥库对象 PKCS12")
    public void getInstanceUseTypeIsPKCS12() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore01.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);
        char[] password = "wangnaixing".toCharArray();
        keyStore.load(fileInputStream,password);

    }

    @Test
    @DisplayName("获取密钥库对象 JKS")
    public void getInstanceUseJKS() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "JKS";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();
        keyStore.load(fileInputStream,password);
    }

你可以加载多个同样类型的证书到KeyStore 存储中。假设此刻你加载了两个同样类型的证书到KeyStore了,我怎么取到我想要的那一个呢?通过别名alias 每一个证书都有一个别名的。

    @Test
    @DisplayName("返回与给定别名关联的证书")
    public void getCertificate() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);

        String alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        System.out.println(certificate);

    }

你记不清楚别名叫什么的情况下,你可以通过aliases() 拿到所有证书的别名数组。

    @Test
    @DisplayName(" 获取所有证书名")
    public void aliases() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);

        Enumeration<String> aliases = keyStore.aliases();
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            System.out.println(alias);   // keystore02
        }


    }

在生成证书的时候,你输入秘钥库访问的密码,这个密码底层采用的是对称加密。同样你通过KeyStore 对象拿到。

    @Test
    @DisplayName(" 返回与给定别名关联的密钥,并使用给定密码恢复该密钥。")
    public void getKey() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        // key = wangnaixing
        Key key = keyStore.getKey(alias, password);
        System.out.println(key);


    }

Certificate

证书的格式,是遵从ITUT X509国际协议标准。在X.509标准中,数字证书的一般格式包含的作用域如下。

  • 1、版本号
  • 2、序列号
  • 3、签名算法
  • 4、发行者
  • 5、有效期
  • 6、主体名
  • 7、公钥
  • 8、发行者ID
  • 9、主体ID
  • 10、扩展域
  • 11、CA(认证机构)对证书的签名

我们得到的Java对象 Certificate 确实封装了这些信息。

    @Test
    @DisplayName("获取证书版本号")
    public void getVersion() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;
        
        int version = x509Certificate.getVersion();
        System.out.println(version);    // 3


    }
    @Test
    @DisplayName("获取证书版本号 序列号是由证书颁发机构CA分配给每个证书的整数 此整数唯一")
    public void getSerialNumber() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;

        BigInteger serialNumber = x509Certificate.getSerialNumber();
        System.out.println(serialNumber);  // 1928866772


    @Test
    @DisplayName("获取证书签名算法 签署整数所用到的算法以及参数")
    public void getSigAlgName() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;

        String sigAlgName = x509Certificate.getSigAlgName();
        System.out.println(sigAlgName); // SHA256withRSA

    }


    @Test
    @DisplayName("获取证书发行者")
    public void getIssuerX500Principal() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;

        X500Principal issuer = x509Certificate.getIssuerX500Principal();
        System.out.println(issuer.getName());    // CN=test,OU=test,O=test,L=test,ST=test,C=test
        
    }
    @Test
    @DisplayName("获取证书有效期 不早于 不晚于")
    public void getNotBeforeAndGetNotAfter() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;

        Date notBefore = x509Certificate.getNotBefore();
        Date notAfter = x509Certificate.getNotAfter();

        System.out.println(DateUtil.format(notBefore, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd")));
        System.out.println(DateUtil.format(notAfter, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd")));
        /**
         * 2022-12-25 21:00:25
         * 2032-12-22 21:00:22
         */
    }

    @Test
    @DisplayName("获取证书主体名 指的证书持有者的名称和有关信息")
    public void getSubjectX500Principal() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException, UnrecoverableKeyException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);
        String  alias = "keystore02";
        Certificate certificate = keyStore.getCertificate(alias);
        X509Certificate x509Certificate = (X509Certificate) certificate;

        X500Principal subject= x509Certificate.getSubjectX500Principal();
        System.out.println(subject); // CN=test, OU=test, O=test, L=test, ST=test, C=test
    }

package com.wnx.naizi;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;

public class CipherTest {



    @Test
    @DisplayName("生成证书对象扩展值")
    public void getExtensionValue() throws CertificateException, IOException {

        String type = "X.509";
        CertificateFactory certificateFactory = CertificateFactory.getInstance(type);


        String certPath = "D:/Microsoft2010.cer";
        FileInputStream fileInputStream = new FileInputStream(certPath);
        Certificate certificate = certificateFactory.generateCertificate(fileInputStream);

        X509Certificate x509Certificate = (X509Certificate) certificate;
        // 策略映射
        byte[] SubjectKeyIdentifier = x509Certificate.getExtensionValue("2.5.29.14");
        // 关键字用法
        byte[] KeyUsage = x509Certificate.getExtensionValue("2.5.29.15");
        // PrivateKey用法
        byte[] PrivateKeyUsage = x509Certificate.getExtensionValue("2.5.29.16");
        //主体可选名
        byte[] SubjectAlternativeName = x509Certificate.getExtensionValue("2.5.29.17");
        // 发行者可选名
        byte[] IssuerAlternativeName = x509Certificate.getExtensionValue("2.5.29.18");
        // 基本约束
        byte[] BasicConstraints = x509Certificate.getExtensionValue("2.5.29.19");
        // 名称约束
        byte[] NameConstraints = x509Certificate.getExtensionValue("2.5.29.30");
        // 策略映射
        byte[] PolicyMappings = x509Certificate.getExtensionValue("2.5.29.33");
        //   授权密钥识别符
        byte[] AuthorityKeyIdentifier = x509Certificate.getExtensionValue("2.5.29.35");
        //    策略约束
        byte[] PolicyConstraints = x509Certificate.getExtensionValue("2.5.29.36");


    }


}
    @Test
    @DisplayName("生成证书认证机构的签名")
    public void getSignature() throws CertificateException, IOException {

        String type = "X.509";
        CertificateFactory certificateFactory = CertificateFactory.getInstance(type);


        String certPath = "D:/Microsoft2010.cer";
        FileInputStream fileInputStream = new FileInputStream(certPath);
        Certificate certificate = certificateFactory.generateCertificate(fileInputStream);

        X509Certificate x509Certificate = (X509Certificate) certificate;
        byte[] signature = x509Certificate.getSignature();
        System.out.println(Arrays.toString(signature));


    }

getPublicKey

除了这些获取信息的API之外,证书的公钥。仔细观察浏览器,只要是https请求,在浏览器某个存储位置,就保存有这个证书,同服务器建立TCP连接之后,他们之间通信都是一种加密通信,也是我们说HTTPS只是TLS+HTTP的原因了。

    @Test
    @DisplayName("从证书获取访问服务器资源公钥")
    public void getPublicKey() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);

        String alias = "keystore02";

        Certificate certificate = keyStore.getCertificate(alias);


        PublicKey publicKey = certificate.getPublicKey();
        System.out.println(publicKey);


    }

verify

证书还携带了CA的签名。验证有没有这个签名存在。

    @Test
    @DisplayName("验证此证书是否使用与指定公钥对应的私钥进行了签名")
    public void verify() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException, NoSuchProviderException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);

        String alias = "keystore02";

        Certificate certificate = keyStore.getCertificate(alias);

        PublicKey publicKey = certificate.getPublicKey();

        certificate.verify(publicKey);
     
        

getEncoded

    @Test
    @DisplayName("返回此证书的编码形式  encoded as ASN.1 DER")
    public void getEncoded() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
        FileInputStream fileInputStream = new FileInputStream("D:/keystore02.p12");
        String type = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(type);

        char[] password = "wangnaixing".toCharArray();

        keyStore.load(fileInputStream,password);

        String alias = "keystore02";

        Certificate certificate = keyStore.getCertificate(alias);
		
		// 转为Base64输出
        String content = new String(Base64.getEncoder().encode(certificate.getEncoded()));
        System.out.println(content);
     
        
    }
MIIDUzCCAjugAwIBAgIEcvgr1DANBgkqhkiG9w0BAQsFADBaMQ0wCwYDVQQGEwR0ZXN0MQ0wCwYDVQQIEwR0ZXN0MQ0wCwYDVQQHEwR0ZXN0MQ0wCwYDVQQKEwR0ZXN0MQ0wCwYDVQQLEwR0ZXN0MQ0wCwYDVQQDEwR0ZXN0MB4XDTIyMTIyNTEzMDAzOFoXDTMyMTIyMjEzMDAzOFowWjENMAsGA1UEBhMEdGVzdDENMAsGA1UECBMEdGVzdDENMAsGA1UEBxMEdGVzdDENMAsGA1UEChMEdGVzdDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJSFLV1dAbefTifo6MV7ZfJKbEsqqO9CP14EBvQ8rSFeHrrFAntz3GNhwjXZZSWVhJJYqyR3wCPZ3F8Oxpen9DlNZH4mRvRcXIisXUZtp/TBUntS0K0428iq09A9hgsxnEX/Bp/YyYeG4YSYQ+xroyiQSdzU8XlIrZT9RUuBmDFtawNeSa0n/2OWGbt/3Df5I9veHDLjBLXW2M6pVmI+zTgRuApGinimIQs6qehwqIrYJXxy4Z+Qf5RPdQoPho/6Mmt6NrKTJWWogwuE2qZk+vWg5oz/eoGt20aZUV7D+izIlrQvmiWdMiZOujhjFWXjtEPq1FUTS49b2nIY4OfN40sCAwEAAaMhMB8wHQYDVR0OBBYEFLJmywmQay8x+356elK3biTmAC6sMA0GCSqGSIb3DQEBCwUAA4IBAQBsXNBCVCgzAWSI3HUm8sxoc237Ml1BzbR/6OoGngaLmDTIoFnflRNUriKcLbytZTGY/V3GkMslLuKPmXGLsqV9swqpdJaBo1YW+jTKrGqItyHgpfP0xRwwTqKC+ZRVGQfwzXB4taOqL/5AUI6eM+Mcm5hR7/7Kj/0ghQ6NkRIEmIyBDcTwNFx46RosBnNa2/e2ShkTGIE8RVNoiYGGpzaJIvE+veuMTkC8gV4ITA6j5KbQsGMtjwUDM+0FDADj+4UqkDSyGmdo0i9iEkWKpmc4wOXq0XaTRBTlokqbajl7fWRbeQuRGlPIBOgmz+2k19n8iMZZJp6OZvrImBswqNbM

CertificateFactory

如果使用KeyTool生成的证书,可以用KeyStore 加载到Java程序内存,然后从这个内存中拿到证书对象,但是生成证书的方式不止KeyTool 这一种方式吧。比如openssl呢?为了满足各种情况下证书文件都能被创建出来,Java提供了CertificateFactory 工厂类来生产。

我们打开本地的证书管理器certmgr

# 1、通过win + r 输入certmgr.msc 进入到证书管理页面
certmgr.msc 

# 2、点击菜单栏的操作选项,并选定查找证书下拉项。

# 3、输入操作内容 比如2010

# 4、 选中某项证书,直接导出就可以。

# 5、给导出的文件指定一个文件名,比如我这边就叫做 Microsoft2010

# 6、最后就可以拿到这个证书了!

38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java
38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java

38_安全密码学基础,Java基础不牢地动山摇!,安全,密码学,java文章来源地址https://www.toymoban.com/news/detail-810608.html

    @Test
    @DisplayName("返回实现指定证书类型的证书工厂对象")
    public void getInstance() throws CertificateException, FileNotFoundException {

        String type = "X.509";
        CertificateFactory certificateFactory = CertificateFactory.getInstance(type);
        System.out.println(certificateFactory);   // java.security.cert.CertificateFactory@358ee631

        String certPath = "D:/Microsoft2010.cer";
        FileInputStream fileInputStream = new FileInputStream(certPath);
        Certificate certificate = certificateFactory.generateCertificate(fileInputStream);

        X509Certificate x509Certificate = (X509Certificate) certificate;


    }

到了这里,关于38_安全密码学基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【网络安全】1.4 密码学基础

    密码学是网络安全的核心组成部分,它帮助我们保护信息,防止未经授权的访问。在这篇文章中,我们将从基础开始,深入了解密码学的基本概念和原理,包括加密、解密、密钥、哈希函数等。我们将尽可能使用简单的语言和实例,以便于初学者理解。 密码学是一门研究信息

    2024年02月07日
    浏览(44)
  • 【现代密码学基础】详解完美安全与不可区分安全

    目录 一. 介绍 二. 不可区分性试验 三. 不可区分性与完美安全 四. 例题 五. 小结 敌手完美不可区分,英文写做perfect adversarial indistinguishability,其中adversarial经常被省略不写,在密码学的论文中经常被简称为IND安全。 完美不可区分与香农的完美安全是类似的。该定义来源于一

    2024年01月21日
    浏览(57)
  • 区块链基础之密码学及安全技术

    1.2 密码学及安全技术 1.2.1 密码学知识 1.2.1.1 Hash函数 Hash(哈希) 哈希函数是一类数学函数,可以在有限合理的时间内,将任意长度的消息压缩为 固定长度的输出值,并且是不可逆的。其输出值称为哈希值,也称为散列值。 哈希算法的应用: 消息认证:确保收到的消息和发送

    2024年02月11日
    浏览(44)
  • 《计算机系统与网络安全》 第四章 密码学基础

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(50)
  • java生成一个符合密码学和安全性的随机秘钥

    有时 我们在生成token 或者完成某种加密形式时会需要一个秘钥 但是 有些时候 项目开发并没有规定用什么秘钥 但是 秘钥都是要有一定格式规范的 我们可以通过以下代码生成一个随机秘钥 重点是 这种一定会符合密码学和安全规范

    2024年02月07日
    浏览(41)
  • 【网络安全】【密码学】【北京航空航天大学】实验三、数论基础(下)【C语言实现】

    1、中国剩余定理(Chinese Remainder Theorem) (1)、算法原理 m1 , m2 , … mk 是一组 两两互素 的正整数,且 M = m1 · m2 · … · mk 为它们的乘积, 则如下的同余方程组: x == a1 (mod m1) x == a2 (mod m2) … x == ak (mod mk) 对于 模M 有唯一的解 x = (M · e1 · a1 / m1 + M · e2 · a2 / m2 + … + M · ek ·

    2024年02月02日
    浏览(51)
  • 【11.10】现代密码学1——密码学发展史:密码学概述、安全服务、香农理论、现代密码学

    参考:密码学发展简史 骆婷老师的《现代密码学(32H)》课程,笔记+查找的资料补充 期末为闭卷考试的形式 密码学早在公元前400多年就已经产生,人类使用密码的历史几乎与使用文字的时间一样长,密码学的发展大致可以分为 3 个阶段: 1949年之前的古典密码学阶段; 1949 年

    2024年02月04日
    浏览(51)
  • 【密码学】量子安全的密码学算法以及原理介绍

    (1)“代数格密码套件”(CRYSTALS)包含两个密码原语Kyber和Dilithium。Kyber是一种抗适应性选择密文攻击(IND-CCA2)安全密钥封装机制,Dilithium是一种高度不可伪造性(EUF-CMA)安全数字签名算法。两种密码都是为了应对量子计算机的攻击,并且在操作过程中只需更改几个参数即

    2024年02月11日
    浏览(64)
  • 密码学与密码安全:理论与实践

    title: 密码学与密码安全:理论与实践 date: 2024/4/10 21:22:31 updated: 2024/4/10 21:22:31 tags: 密码学 加密算法 安全协议 密码分析 密码安全 实际应用 未来发展 密码学是研究如何保护信息安全的学科,旨在确保信息在传输和存储过程中不被未授权的人所访问、修改或破坏。密码学涉及

    2024年04月11日
    浏览(45)
  • 密码学:可证明安全

    观看浙江大学暑期crypto school讲座的可证明安全有感,总结如下: 目录 · 概述 · 公钥密码 · 单向函数 · 离散对数 · DH密钥协商协议 · 用可证明安全证明DH密钥协商协议的安全性 可证明安全主要分为三个步骤: 确定威胁模型; 其次构造方案; 给出一个正式的安全性证明。

    2024年02月02日
    浏览(99)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包