【Java基础】了解Java安全体系JCA,使用BouncyCastle的ED25519算法生成密钥对、数据签名

news2024/9/30 3:31:51

文章目录

  • 一.Java安全体系结构
  • 二.JCA和JCE
  • 三.CSP(加密服务提供程序)与Engine类
    • 1.CSP
    • 2.Engine类
      • 如何使用引擎类
  • 四.查看当前JDK支持的算法服务提供商(Provider)
  • 五.BouncyCastle是什么
  • 六.如何使用BouncyCastle?
  • 七.bouncycastle实现ED25519工具类

一.Java安全体系结构

总共分为4个部分:

  • JCA( Java Cryptography Architecture, Java加密体系结构):提供了基本的加密框架,包括证书、数字签名、消息摘要和密钥对产生器等。它允许开发者通过Java API来访问和操作加密相关的功能。
  • JCE( Java Cryptography Extension, Java加密扩展包):JCE在JCA的基础上作了扩展, 提供了各种加密算法、 消息摘要算法(散列算法、哈希算法)和密钥管理等功能。JCE的实现主要在javax.crypto包( 及其子包)
  • JSSE( Java Secure Sockets Extension, Java安全套接字扩展包):JSSE提供了基于SSL( Secure Sockets Layer,安全套接字层) 的加密功能。。这有助于确保在网络传输过程中的信息安全,防止数据被窃取或篡改。
  • JAAS( Java Authentication and Authentication Service, Java认证和授权服务):用于Java应用程序的认证和授权。它允许程序根据用户的身份和权限来限制对某些资源的访问,从而增强了应用程序的安全性。

二.JCA和JCE

JCA: Java密码体系结构 Java Cryptography Architecture

  • JCE(Java Cryptography Extension),在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了2部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。

    • 现在JCE已经捆绑在JDK中,所以,这里JCE是JCA的一部分
  • JCA包含一个提供者【Provider】体系结构和一组用于数字签名消息摘要(哈希)证书和证书验证密(对称/非对称块/流密码),密钥生成管理安全随机数生成等等的API。

JCA包含两个组件:

  • 定义和支持Provider为其提供实现的加密服务的框架。 这个框架包含了诸如java.security,javax.crypto,javax.crypto.spec和javax.crypto.interfaces等软件包

    • JCA相关代码位于JDK的rt.jar中的java.security包及其子包中。

    • JCE相关代码位于JDK的jce.jar中的javax.crypto包及其子包中。

      • java.security.Provider类是所有加密与安全算法的父类。
  • Sun,SunRsaSign,SunJCE等实际提供者的具体的加密实现。

  • 通过JCA统一的、可扩展的一套用于实现加密服务的基础功能基础API,,打包成一个Provider服务( 安全提供者),也就是一个实现JCA标准的jar包可以动态地加载到Java运行环境中。

    • 而开发者在使用只需根据JCA框架提供的统一接口来调用各种第三方服务商加密算法、密钥管理等功能,而无需关心底层的实现细节

三.CSP(加密服务提供程序)与Engine类

1.CSP

在Java中,并没有直接称为"Cryptographic Service Provider (CSP)"的官方组件或术语。 然而,Java有一个类似的机制,即Java Cryptography Extension (JCE)中的Provider机制,它允许第三方实现并集成加密服务

  • java.security.Provider是所有安全算法提供实现的父类。 每个CSP都包含这个类的一个实例,它包含了提供者的名字,并列出了它实现的所有安全服务/算法
  • 每个Provider可以包含多种类型的Engine类,这些Engine类是实现特定加密算法或功能的基类。这些基类定义了算法的通用接口,而具体的实现则由不同的Provider提供

2.Engine类

Engine类为特定类型的密码服务提供的统一接口,不依赖于特定的密码算法或提供者。

  • 加密,数字签名,消息摘要等
  • 密钥和算法参数
  • 密钥库或证书

消息摘要引擎(Message Digest Engine):

  • 作用:用于数据完整性校验。它将输入的任意长度消息进行哈希运算,生成一个固定长度的摘要值。
  • 常见算法:包括MD5、SHA-1等。
  • 使用场景:在保证消息完整的前提下,即使消息长度非常大,也可以通过摘要值的校验实现快速和安全的数据校验。
  • java.security.MessageDigest

数字签名引擎(Digital Signature Engine):

  • 作用:用于验证数据真实性和完整性。
  • 使用场景:常用于电子商务、在线金融等领域,用于保证交易的安全性。
  • java.security.Signature

对称加密引擎:

  • 使用相同的密钥进行加密和解密数据。
  • javax.crypto.Cipher类来进行对称加密。
  • 常见算法:包括DES、AES和Blowfish等。

非对称加密引擎:

  • 使用一对密钥(公钥和私钥)进行加密和解密。发送方使用接收方的公钥加密数据,接收方使用自己的私钥解密数据。
  • 使用javax.crypto.Cipher类进行非对称加密操作。

消息认证码(Message Authentication Code,MAC)引擎

  • Mac是一个带密钥的hash算法,首先使用密钥初始化后生成散列值,以保护消息的完整性。
  • java.crypto.Mac

密钥生成器:

  • KeyGenerator:用于生成指定算法的对称密钥。
  • KeyPairGenerator:用于生成一对适用于指定算法的非对称加密算法的密钥对。

KeyFactory

  • 用于从某种类型的密钥规范(key specification)中导出密钥的引擎。

SecretKeyFactory

  • 用于从原始密钥序列化数据中导出密钥的引擎。

SecureRandom

  • 用于生成随机或伪随机数字。

如何使用引擎类

1.使用KeyPairGenerator引擎类生成公钥和私钥的密钥对

  • 要使用KeyPairGenerator生成密钥对,你需要首先获取对应算法的实例,然后通过调用genKeyPair()方法来生成密钥对。
public class KeyPairGeneratorExample {
    public static void main(String[] args) {
        try {
            // 创建一个KeyPairGenerator实例,指定密钥对的算法为RSA
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

            // 初始化KeyPairGenerator,指定密钥长度
            keyPairGenerator.initialize(2048); // 2048位密钥长度

            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.genKeyPair();

            // 获取公钥和私钥
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            // 打印公钥和私钥信息(在实际应用中,不应该直接打印或输出私钥)
            System.out.println("Public Key: " + publicKey);
            System.out.println("Private Key: " + privateKey);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

2.使用Mac引擎类,生成消息摘要算法

  • 使用Mac算法,先获取一个Mac实例,指定所使用的算法(如HmacSHA256),然后提供密钥和要计算MAC的消息。
public class MacExample {
    public static void main(String[] args) {
        try {
            // 创建一个Mac实例,指定算法为HmacSHA256
            Mac mac = Mac.getInstance("HmacSHA256");

            // 初始化Mac实例,使用指定的密钥
            byte[] keyBytes = "mySecretKey".getBytes(StandardCharsets.UTF_8);
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "HmacSHA256");
            mac.init(secretKeySpec);

            // 提供要计算MAC的消息
            byte[] message = "Hello, World!".getBytes(StandardCharsets.UTF_8);

            // 计算MAC值
            byte[] macBytes = mac.doFinal(message);

            // 打印MAC值(通常以十六进制形式表示)
            System.out.println("MAC: " + bytesToHex(macBytes));

        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    // 辅助方法,将字节数组转换为十六进制字符串
    private static String bytesToHex(byte[] hash) {
        StringBuilder hexString = new StringBuilder(2 * hash.length);
        for (int i = 0; i < hash.length; i++) {
            String hex = Integer.toHexString(0xff & hash[i]);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }
}

四.查看当前JDK支持的算法服务提供商(Provider)

  • 当前版本jdk1.8
public class JavaProividerTest {
    public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException {
        System.out.println(printAllSecurityProvidersInMdTable());
    }


    // 输出MarkDown格式的表格,具体内容见下表
    public static String printAllSecurityProvidersInMdTable() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Provider Name(供应商名称)|Provider Version(供应商版本)|Algorithm Type(算法类型)|Algorithm Name(算法名称)\r\n");
        stringBuilder.append("|:-|:-|:-|:-\r\n");
        Map<String, Map<String, String>> providers2Algorithms = Arrays.stream(Security.getProviders())
                .collect(Collectors.toMap(provider -> provider.getName() + "@" + provider.getVersion(), provider -> provider.getServices().stream().collect(Collectors.toMap(service -> service.getType(), service -> service.getAlgorithm(), (algorithm1, algorithm2) -> algorithm1 + "@" + algorithm2))));
        providers2Algorithms.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entryProvider -> {
            String[] provider = entryProvider.getKey().split("@");
            Map<String, String> algoType2AlgoName = entryProvider.getValue();
            int[] rowNumber = {0};
            algoType2AlgoName.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(entryAlgorithm -> {
                StringBuilder algorithmCellStr = new StringBuilder();
                int[] numberOfAlgorithm = {1};
                Arrays.stream(entryAlgorithm.getValue().split("@")).sorted(String::compareTo).forEachOrdered(algorithm -> {
                    algorithmCellStr.append(algorithm);
                    if (0 == numberOfAlgorithm[0] % 1) {
                        algorithmCellStr.append("<br>");
                    }
                    numberOfAlgorithm[0]++;
                });

                stringBuilder.append(String.format("|%s|%s|%s|%s\r\n", 0 == rowNumber[0] ? provider[0] : "", 0 == rowNumber[0] ? provider[1] : "", entryAlgorithm.getKey(), algorithmCellStr.toString()));
                rowNumber[0]++;
            });
        });

        return stringBuilder.toString();
    }

    // 输出纯文本格式
    public static void printAllSecurityProviders() {
        for (Provider provider : Security.getProviders()) {
            System.out.println("Provider: " + provider.getName() + " (ver " + provider.getVersion() + ")");
            System.out.print("  Algorithms: ");
            ArrayList<String> algos = new ArrayList<String>();
            for (Provider.Service service : provider.getServices()) {
                algos.add(String.format("%s (%s)", service.getAlgorithm(), service.getType()));
            }
            java.util.Collections.sort(algos);
            String algorsStr = algos.toString();
            algorsStr = algorsStr.substring(1, algorsStr.length() - 1);
            System.out.println(algorsStr);
            System.out.println();
        }
    }
}

当前JDK版本为1.8,每个JDK安装都默认安装并配置了一个或多个provider包。

    public static void main(String[] args) {
        System.out.println("-------列出加密服务提供者-----");
        Provider[] pro = Security.getProviders();
        for (Provider p : pro) {
            System.out.println("Provider:" + p.getName() + " - version:" + p.getVersion());
            System.out.println(p.getInfo());
        }
        System.out.println("");
        System.out.println("-------列出系统支持的消息摘要算法(散列算法、哈希算法):");
        for (String s : Security.getAlgorithms("MessageDigest")) {
            System.out.println(s);
        }
        System.out.println("-------列出系统支持的生成公钥和私钥对的算法:");
        for (String s : Security.getAlgorithms("KeyPairGenerator")) {
            System.out.println(s);
        }
    }
  • 可以看到默认情况下java1.8已经支持市面上绝大多数常见算法
    在这里插入图片描述

有一些算法JDK中的Provider并没有提供,用户可以静态或动态添加其他provider。

  • 除了jdk自带的加解密实现外,另外2个主要的加解密算法的提供者为bouncy castleapache common codec,它们提供了额外的算法以及在JDK基础上提高了易用性。其中bouncy castle就提供了Provider的扩展,补充了JDK没有实现的一些算法

下面我们就以bouncy castle为例,看看如何添加新的Provider扩展:

五.BouncyCastle是什么

  • BouncyCastle(轻量级密码术包)是一种用于 Java 平台的开源的轻量级加密包;Bouncycstle 包含了大量哈希算法和加密算法,包括Java标准库没有的一些算法,如非对称加密算法ECDSA(椭圆曲线数字签名算法),并提供JCE 1.2.1的实现、RipeMD160哈希算法、椭圆曲线数字签名算法分支ED25519

六.如何使用BouncyCastle?

  • maven中央仓库
    在这里插入图片描述

引入bouncycastle依赖

        <!--        <dependency>-->
        <!--            <groupId>org.bouncycastle</groupId>-->
        <!--            <artifactId>bcprov-jdk18on</artifactId>-->
        <!--            <version>1.77</version>-->
        <!--        </dependency>-->


        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>

Java标准库的java.security包提供了一种标准机制,允许第三方提供商无缝接入。使用BouncyCastle提供的ED25519算法,需要先把BouncyCastle注册一下:

  • 加入一行代码:在java应用程序启动注册BouncyCastle提供的所有哈希算法和加密算法
    static {
        //注册只需要在启动时进行一次,后续就可以使用BouncyCastle提供的所有哈希算法和加密算法。
        Security.addProvider(new BouncyCastleProvider());
    }

在这里插入图片描述
执行代码:

  1. 可以看到bouncycastle作为加密服务提供者已经注册到java程序中
    在这里插入图片描述

  2. 系统支持的哈希算法和非对称加密算法也多出了很多

-------列出系统支持的消息摘要算法(散列算法、哈希算法):
SHA-1
SHA-384
HARAKA-256
SKEIN-512-256
SKEIN-1024-384
BLAKE2B-160
SHA
KECCAK-288
WHIRLPOOL
SKEIN-512-384
SHA-224
SM3
BLAKE2B-512
OID.1.0.10118.3.0.55
GOST3411-2012-512
KECCAK-256
SKEIN-512-128
BLAKE2B-384
SHAKE256-512
SKEIN-256-160
DSTU7564-256
SHA-256
BLAKE2S-224
SHA3-256
KECCAK-384
SKEIN-256-128
DSTU7564-384
HARAKA-512
SHAKE128-256
KECCAK-224
SKEIN-512-512
SKEIN-1024-512
SKEIN-512-160
GOST3411
BLAKE2B-256
SKEIN-1024-1024
SHA3-384
BLAKE2S-256
SHA-512/224
TIGER
RIPEMD256
SKEIN-256-256
SHA3-224
SHA3-512
RIPEMD320
RIPEMD160
GOST3411-2012-256
KECCAK-512
SKEIN-512-224
BLAKE2S-160
SHA-512/256
MD2
RIPEMD128
MD4
SHA-512
SKEIN-256-224
MD5
BLAKE2S-128
DSTU7564-512
-------列出系统支持的生成公钥和私钥对的算法(非对称加密算法):
ECDH
DH
DIFFIEHELLMAN
ECGOST3410-2012
X448
ECDHC
ED25519
GOST3410
ELGAMAL
DSA
ED448
DSTU4145
XDH
EC
ECDSA
RSA
X25519
ECGOST3410
ECIES
ECDHWITHSHA1KDF
RSASSA-PSS
EDDSA
ECMQV

七.bouncycastle实现ED25519工具类

Ed25519是椭圆曲线数字签名算法(ECDSA)的一个重要分支

特点:

  • 安全性: Ed25519相对于传统的ECDSA有着更好的安全性。
  • 效率: 它的运行效率非常高,适合在各种设备上执行,包括移动设备。
  • 短签名: 它产生的签名非常短,只有64字节。
    • 可用于区块链签名。签名过程不依赖随机数生成器,不依赖哈希函数的抗碰撞性,没有时间通道攻击的问题。
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator;
import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

/**
 * BouncyCastle是一个提供了很多哈希算法和加密算法的第三方库。它提供了Java标准库没有的一些算法,例如,RipeMD160哈希算法。其它第三方库还有Commons Codec等。
 * 你可以使用Bouncy Castle的API来生成密钥对,然后使用私钥对消息进行签名,使用公钥来验证签名。
 */
public class Ed25519Utils {
    static {
        //注册只需要在启动时进行一次,后续就可以使用BouncyCastle提供的所有哈希算法和加密算法。
        Security.addProvider(new BouncyCastleProvider());
    }

    //1.初始化密钥对
    private static AsymmetricCipherKeyPair KEY_PAIR = generateKeyPair();
    //2.创建一个私钥和私钥
    private static Ed25519PrivateKeyParameters PRIVATE_KEY = getPrivateKey(KEY_PAIR);
    private static Ed25519PublicKeyParameters PUBLIC_KEY = getPublicKey(KEY_PAIR);


    /**
     * 初始化上下文
     */
    public static void initContext() {
        KEY_PAIR = generateKeyPair();
        PRIVATE_KEY = getPrivateKey(KEY_PAIR);
        PUBLIC_KEY = getPublicKey(KEY_PAIR);
    }

    /**
     * 获取私钥对消息签名的Base64格式字符串
     *
     * @param message
     * @return
     */
    public static String getPrivateKeySignMessageBase64(String message) {
        byte[] messageBytes = getBytes(message);
        System.out.println("签名消息:" + message + "\n");
        //使用私钥对消息进行签名,然后将私钥签名编码为Base64格式,最后将base64私钥签名进行url编码
        byte[] privateSignatureByte = privateKeySign(PRIVATE_KEY, messageBytes);

        return base64EncodeToString(privateSignatureByte);
    }

    /**
     * 使用公钥来验证签名。
     *
     * @param message           签名消息
     * @param privateBase64Sign 私钥对消息签名的Base64格式字符串
     */
    public static boolean publicKeyCheckSign(String message, String privateBase64Sign) {
        //初始化签名器
        Ed25519Signer verifier = new Ed25519Signer();
        verifier.init(false, PUBLIC_KEY);
        //执行验签
        verifier.update(getBytes(message), 0, getBytes(message).length);
        //验签结果
        return verifier.verifySignature(Base64.getDecoder().decode(privateBase64Sign));
    }

    /**
     * 使用私钥对消息进行签名
     *
     * @param privateKey   私钥
     * @param messageBytes 消息  "account=zichangaibantest1@163.com&captcha=111111&code=WrPQctXMOu&pub_key=" + publicBase64Str + "&type=2";
     * @return 私钥签名后的base编码消息
     */
    public static byte[] privateKeySign(Ed25519PrivateKeyParameters privateKey, byte[] messageBytes) {
        //初始化签名器
        Ed25519Signer signer = new Ed25519Signer();
        signer.init(true, privateKey);
        // 执行签名
        signer.update(messageBytes, 0, messageBytes.length);

        //7.将私钥签名编码为Base64格式
        return signer.generateSignature();
    }

    private static AsymmetricCipherKeyPair generateKeyPair() {
        //1.创建ed25519密钥生成器
        Ed25519KeyPairGenerator keyPairGenerator = new Ed25519KeyPairGenerator();
        //密钥生成参数,需要指定随机种子
        SecureRandom secureRandom = new SecureRandom();
        Ed25519KeyGenerationParameters keyGenerationParameters = new Ed25519KeyGenerationParameters(secureRandom);
        keyPairGenerator.init(keyGenerationParameters);

        //2.生成公私钥对
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 获取私钥对象
     *
     * @param keyPair
     * @return
     */
    private static Ed25519PrivateKeyParameters getPrivateKey(AsymmetricCipherKeyPair keyPair) {
        return (Ed25519PrivateKeyParameters) keyPair.getPrivate();
    }

    /**
     * 获取公钥对象
     *
     * @param keyPair
     * @return
     */
    private static Ed25519PublicKeyParameters getPublicKey(AsymmetricCipherKeyPair keyPair) {
        return (Ed25519PublicKeyParameters) keyPair.getPublic();
    }

    /**
     * 获取私钥字节
     *
     * @param privateKey
     * @return
     */
    private static byte[] getPrivateByte(Ed25519PrivateKeyParameters privateKey) {
        //序列化私钥
        return privateKey.getEncoded();
    }

    /**
     * 获取公钥字节
     *
     * @param publicKey
     * @return
     */
    private static byte[] getPublicByte(Ed25519PublicKeyParameters publicKey) {
        //序列化公钥
        return publicKey.getEncoded();
    }

    /**
     * 获取base64编码后字符串
     *
     * @param bytes
     * @return 如:/85uEv81XgrIbuHqnUMVRSrS8C/tr9jn0NBSv0wb1Dk=  会携带/、=之类特殊符号
     */
    public static String base64EncodeToString(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 获取私钥base64编码后字符串
     *
     * @param privateBase64Str 如:/85uEv81XgrIbuHqnUMVRSrS8C/tr9jn0NBSv0wb1Dk=  会携带/、=之类特殊符号
     * @return
     */
    public static String urlEncodeStr(String privateBase64Str)  {
        try {
            return URLEncoder.encode(privateBase64Str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] getBytes(String str) {
        return str.getBytes(StandardCharsets.UTF_8);
    }

    /**
     * 获取base64编码公钥字符串
     *
     * @return
     */
    public static String getBase64Public() {
        byte[] publicBytes = getPublicByte(PUBLIC_KEY);
        return base64EncodeToString(publicBytes);
    }

    /**
     * 获取url编码后的 获取base64编码公钥字符串
     *
     * @return
     * @throws
     */
    public static String getBase64UrlEncodePublic()  {
        return urlEncodeStr(getBase64Public());
    }

    /**
     * 获取base64编码私钥字符串
     *
     * @return
     */
    public static String getBase64Private() {
        byte[] priavteBytes = getPrivateByte(PRIVATE_KEY);
        return base64EncodeToString(priavteBytes);
    }

    /**
     * 获取url编码后的 获取base64编码私钥字符串
     *
     * @return
     * @throws
     */
    public static String getBase64UrlEncodePrivate()  {
        return urlEncodeStr(getBase64Private());
    }
}

测试代码

    public static void main(String[] args)  {

        for (int i = 0; i < 1; i++) {
             Ed25519Utils.initContext();
            //1.将publicBytes编码为Base64格式,然后对Base64公钥进行url编码
            String publicBase64 = Ed25519Utils.getBase64Public();
            String urlEncodedBase64Public = Ed25519Utils.urlEncodeStr(publicBase64);
            System.out.println("base64公钥:" + publicBase64);
            System.out.println("URL编码后的base64公钥为:" + urlEncodedBase64Public + "\n");


            //2.将privateBytes编码为Base64格式,然后对Base64私钥进行url编码
            String privateBase64 = Ed25519Utils.getBase64Private();
            String urlEncodedBase64Private = Ed25519Utils.urlEncodeStr(privateBase64);
            System.out.println("base64私钥:" + privateBase64);
            System.out.println("URL编码后的base64私钥为:" + urlEncodedBase64Private + "\n");


            //3.拼接公钥到请求消息中,同时序列化消息
            String message = "account=zichangaibantest1@163.com&captcha=111111&code=WrPQctXMOu&pub_key=publicKey&type=2";
            // 需要签名的数据,根据key进行排序,然后序列化签名
            message = message.replaceAll("publicKey", publicBase64);

            //4.使用私钥对消息进行签名,然后将私钥签名编码为Base64格式,最后将base64私钥签名进行url编码
            String privateBase64Sign = Ed25519Utils.getPrivateKeySignMessageBase64(message);
            String urlEncodePrivateBase64Sign = Ed25519Utils.urlEncodeStr(privateBase64Sign);
            System.out.println("bas4私钥签名消息为:" + privateBase64Sign);
            System.out.println("私钥签名消息:" + urlEncodePrivateBase64Sign + "\n");

            //5.使用公钥验证签名
            boolean isValid = Ed25519Utils.publicKeyCheckSign(message, privateBase64Sign);
            System.out.println("验证私钥签名是否正确 i: " + isValid);
            System.out.println("----------------------------------------------------");
            System.out.println("----------------------------------------------------");
        }

    }
}

执行结果
在这里插入图片描述

Provider NameProvider VersionAlgorithm TypeAlgorithm Name
SUN1.8AlgorithmParameterGeneratorDSA
AlgorithmParametersDSA
CertPathBuilderPKIX
CertPathValidatorPKIX
CertStoreCollection
LDAP
com.sun.security.IndexedCollection
CertificateFactoryX.509
ConfigurationJavaLoginConfig
KeyFactoryDSA
KeyPairGeneratorDSA
KeyStoreCaseExactJKS
DKS
JKS
MessageDigestMD2
MD5
SHA
SHA-224
SHA-256
SHA-384
SHA-512
PolicyJavaPolicy
SecureRandomSHA1PRNG
SignatureNONEwithDSA
SHA1withDSA
SHA224withDSA
SHA256withDSA
SunEC1.8AlgorithmParametersEC
KeyAgreementECDH
KeyFactoryEC
KeyPairGeneratorEC
SignatureNONEwithECDSA
SHA1withECDSA
SHA224withECDSA
SHA256withECDSA
SHA384withECDSA
SHA512withECDSA
SunJCE1.8AlgorithmParameterGeneratorDiffieHellman
AlgorithmParametersAES
Blowfish
DES
DESede
DiffieHellman
GCM
OAEP
PBE
PBES2
PBEWithHmacSHA1AndAES_128
PBEWithHmacSHA1AndAES_256
PBEWithHmacSHA224AndAES_128
PBEWithHmacSHA224AndAES_256
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
PBEWithHmacSHA384AndAES_128
PBEWithHmacSHA384AndAES_256
PBEWithHmacSHA512AndAES_128
PBEWithHmacSHA512AndAES_256
PBEWithMD5AndDES
PBEWithMD5AndTripleDES
PBEWithSHA1AndDESede
PBEWithSHA1AndRC2_128
PBEWithSHA1AndRC2_40
PBEWithSHA1AndRC4_128
PBEWithSHA1AndRC4_40
RC2
CipherAES
AESWrap
AESWrap_128
AESWrap_192
AESWrap_256
AES_128/CBC/NoPadding
AES_128/CFB/NoPadding
AES_128/ECB/NoPadding
AES_128/GCM/NoPadding
AES_128/OFB/NoPadding
AES_192/CBC/NoPadding
AES_192/CFB/NoPadding
AES_192/ECB/NoPadding
AES_192/GCM/NoPadding
AES_192/OFB/NoPadding
AES_256/CBC/NoPadding
AES_256/CFB/NoPadding
AES_256/ECB/NoPadding
AES_256/GCM/NoPadding
AES_256/OFB/NoPadding
ARCFOUR
Blowfish
DES
DESede
DESedeWrap
PBEWithHmacSHA1AndAES_128
PBEWithHmacSHA1AndAES_256
PBEWithHmacSHA224AndAES_128
PBEWithHmacSHA224AndAES_256
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
PBEWithHmacSHA384AndAES_128
PBEWithHmacSHA384AndAES_256
PBEWithHmacSHA512AndAES_128
PBEWithHmacSHA512AndAES_256
PBEWithMD5AndDES
PBEWithMD5AndTripleDES
PBEWithSHA1AndDESede
PBEWithSHA1AndRC2_128
PBEWithSHA1AndRC2_40
PBEWithSHA1AndRC4_128
PBEWithSHA1AndRC4_40
RC2
RSA
KeyAgreementDiffieHellman
KeyFactoryDiffieHellman
KeyGeneratorAES
ARCFOUR
Blowfish
DES
DESede
HmacMD5
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512
RC2
SunTls12Prf
SunTlsKeyMaterial
SunTlsMasterSecret
SunTlsPrf
SunTlsRsaPremasterSecret
KeyPairGeneratorDiffieHellman
KeyStoreJCEKS
MacHmacMD5
HmacPBESHA1
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512
PBEWithHmacSHA1
PBEWithHmacSHA224
PBEWithHmacSHA256
PBEWithHmacSHA384
PBEWithHmacSHA512
SslMacMD5
SslMacSHA1
SecretKeyFactoryDES
DESede
PBEWithHmacSHA1AndAES_128
PBEWithHmacSHA1AndAES_256
PBEWithHmacSHA224AndAES_128
PBEWithHmacSHA224AndAES_256
PBEWithHmacSHA256AndAES_128
PBEWithHmacSHA256AndAES_256
PBEWithHmacSHA384AndAES_128
PBEWithHmacSHA384AndAES_256
PBEWithHmacSHA512AndAES_128
PBEWithHmacSHA512AndAES_256
PBEWithMD5AndDES
PBEWithMD5AndTripleDES
PBEWithSHA1AndDESede
PBEWithSHA1AndRC2_128
PBEWithSHA1AndRC2_40
PBEWithSHA1AndRC4_128
PBEWithSHA1AndRC4_40
PBKDF2WithHmacSHA1
PBKDF2WithHmacSHA224
PBKDF2WithHmacSHA256
PBKDF2WithHmacSHA384
PBKDF2WithHmacSHA512
SunJGSS1.8GssApiMechanism1.2.840.113554.1.2.2
1.3.6.1.5.5.2
SunJSSE1.8KeyFactoryRSA
KeyManagerFactoryNewSunX509
SunX509
KeyPairGeneratorRSA
KeyStorePKCS12
SSLContextDefault
TLS
TLSv1
TLSv1.1
TLSv1.2
SignatureMD2withRSA
MD5andSHA1withRSA
MD5withRSA
SHA1withRSA
TrustManagerFactoryPKIX
SunX509
SunMSCAPI1.8CipherRSA
RSA/ECB/PKCS1Padding
KeyPairGeneratorRSA
KeyStoreWindows-MY
Windows-ROOT
SecureRandomWindows-PRNG
SignatureMD2withRSA
MD5withRSA
NONEwithRSA
SHA1withRSA
SHA256withRSA
SHA384withRSA
SHA512withRSA
SunPCSC1.8TerminalFactoryPC/SC
SunRsaSign1.8KeyFactoryRSA
KeyPairGeneratorRSA
SignatureMD2withRSA
MD5withRSA
SHA1withRSA
SHA224withRSA
SHA256withRSA
SHA384withRSA
SHA512withRSA
SunSASL1.8SaslClientFactoryCRAM-MD5
DIGEST-MD5
EXTERNAL
GSSAPI
NTLM
PLAIN
SaslServerFactoryCRAM-MD5
DIGEST-MD5
GSSAPI
NTLM
XMLDSig1.8KeyInfoFactoryDOM
TransformServicehttp://www.w3.org/2000/09/xmldsig#base64
http://www.w3.org/2000/09/xmldsig#enveloped-signature
http://www.w3.org/2001/10/xml-exc-c14n#
http://www.w3.org/2001/10/xml-exc-c14n#WithComments
http://www.w3.org/2002/06/xmldsig-filter2
http://www.w3.org/2006/12/xml-c14n11
http://www.w3.org/2006/12/xml-c14n11#WithComments
http://www.w3.org/TR/1999/REC-xpath-19991116
http://www.w3.org/TR/1999/REC-xslt-19991116
http://www.w3.org/TR/2001/REC-xml-c14n-20010315
http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments
XMLSignatureFactoryDOM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1537901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepLabv1网路介绍

模型创新点 在论文引言中&#xff0c;作者提出了目前语义分割存在的问题&#xff0c;并且给出了解决办法&#xff1a; 下采样会导致我们图像空间分辨率降低——解决办法 使用膨胀卷积 目前语义分割网络基本都是采用CNN网络作为主干网络&#xff0c;但是CNN网络主要适用于目标检…

获取淘宝商品评论的爬虫技术分享(已封装API,可测试)

item_review-获得淘宝商品评论 公共参数 请求地址: taobao/item_review 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,it…

鸿蒙Harmony应用开发—ArkTS-@Provide装饰器和@Consume装饰器:与后代组件双向同步

Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provide装饰的变…

基于python+vue文学名著分享系统的设计与实现flask-django-nodejs-php

随着世界经济信息化、全球化的到来和互联网的飞速发展&#xff0c;推动了各行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、动态的、交互友好的、高效的文学名著分享系统。当前的信息管理存在工作效率…

设计模式之单例模式解析

单例模式 1&#xff09;动机 对于软件系统的某些类&#xff0c;无须创建多个实例&#xff0c;如 Windows 系统的任务管理器&#xff0c;重复对象会浪费系统资源。 2&#xff09;概述 1.定义 确保某个类只有一个实例&#xff0c;而且自行实例化&#xff0c;并向整个系统提供…

Android Kotlin(六)协程的并发问题

书接上回&#xff1a;Android Kotlin知识汇总&#xff08;三&#xff09;Kotlin 协程 协程的并发问题 在一个协程中&#xff0c;循环创建10个子协程且单独运行各自Default线程中&#xff0c;并让每个子协程对变量 i 进行1000次自增操作。示例如下&#xff1a; fun main() …

Jupyter服务器端为R语言安装readr包

1.登录debian服务器 方式1.Windows10中可利用putty登录linux服务器 方式2.自从搭建了Jupyter服务器后&#xff0c;还可以从juypyter的终端来登录linux服务器 2.进入R语言命令行 3.安装readr包 >install.packages(‘readr’) …

使用CSS3画出一个叮当猫HTML源码

我们经常使用PS或者Flash制作动画&#xff0c;本文则介绍了如何用CSS3画出个叮当猫&#xff0c;实现过程很有趣&#xff0c;感兴趣的朋友可以参考一下 首先&#xff0c;先把HTML结构搭建好&#xff1a; <div class"wrapper"> <!--叮当猫整体--> <di…

DP动态规划入门(数字三角形、破损的楼梯、安全序列)

一、动态规划&#xff08;DP&#xff09;简介 动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是运筹学的一个分支&#xff0c;它是一种通过将复杂问题分解成多个重叠的子问题&#xff0c;并通过子问题的解来构建整个问题的解的算法。在动态规划中&am…

2016年认证杯SPSSPRO杯数学建模D题(第一阶段)NBA是否有必要设立四分线解题全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 D题 NBA是否有必要设立四分线 原题再现 NBA 联盟从 1946 年成立到今天&#xff0c;一路上经历过无数次规则上的变迁。有顺应民意、皆大欢喜的&#xff0c;比如 1973 年在技术统计中增加了抢断和盖帽数据&#xff1b;有应运而生、力挽狂澜的&am…

.NET Core 服务实现监控可观测性最佳实践

前言 本次实践主要是介绍 .Net Core 服务通过无侵入的方式接入观测云进行全面的可观测。 环境信息 系统环境&#xff1a;Kubernetes编程语言&#xff1a;.NET Core ≥ 2.1日志框架&#xff1a;Serilog探针类型&#xff1a;ddtrace 接入方案 准备工作 DataKit 部署 DataK…

软件推荐 篇三十七:安卓软件推荐IP Tools「IP工具」:全面解析网络状态与管理的必备神器

引言&#xff1a; 随着互联网的普及&#xff0c;网络已经成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都需要通过网络来进行各种操作。然而&#xff0c;网络问题的出现往往会给我们带来诸多困扰。为了更好地管理和优化网络&#xff0c;我们…

V2X技术与智能传感器的完美融合:提升城市道路安全

在科技不断创新的今天&#xff0c;城市交通领域涌现了大量新技术。有时候我们不仅仅需要独立应用这些新技术来实现交通的变革&#xff0c;更需要将它们巧妙地结合连接起来&#xff0c;以获取更高效更安全的交通环境。本文将探讨V2X技术与智能传感器的结合&#xff0c;如何在城市…

如何使用 Elasticsearch 作为向量数据库

在今天的文章中&#xff0c;我们将很快地通过 Docker 来快速地设置 Elasticsearch 及 Kibana&#xff0c;并设置 Elasticsearch 为向量搜索。 拉取 Docker 镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2 docker pull docker.elastic.co/kibana/kiba…

python网络相册设计与实现flask-django-nodejs-php

此系统设计主要采用的是python语言来进行开发&#xff0c;采用django框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安…

平衡隐私与效率,Partisia Blockchain 解锁数字安全新时代

原文&#xff1a;https://cointelegraph.com/news/exploring-multiparty-computations-role-in-the-future-of-blockchain-privacy&#xff1b; https://medium.com/partisia-blockchain/unlocking-tomorrow-outlook-for-mpc-in-2024-and-beyond-cb170e3ec567 编译&#xff1…

学习笔记Day14:Linux下软件安装

软件安装 Anaconda 所有语言的包(package)、依赖(dependency)和环境(environment)管理器&#xff0c;类似应用商店 Conda < Miniconda < Anaconda&#xff08;有交互界面&#xff09; Linux下Miniconda即可 安装Miniconda 搜索北外/清华miniconda镜像网站&#xff…

网络安全笔记-day6,NTFS安全权限

文章目录 NTFS安全权限常用文件系统文件安全权限打开文件安全属性修改文件安全权限1.取消父项继承权限2.添加用户访问权限3.修改用户权限4.验证文件权限5.总结权限 强制继承父项权限文件复制移动权限影响跨分区同分区 总结1.权限累加2.管理员最高权限2.管理员最高权限 NTFS安全…

利用CSS3实现正在加载效果

一、代码区域 1.1css3代码 <style>* {padding: 0;margin: 0;list-style: none;}.loading {width: 300px;height: 100px;margin: 100px auto;}.loading ul {height: 100px;width: 65px;margin: 0 auto;display: flex;align-items: center;}.loading ul li {margin: 0 5p…