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

文章目录
  • 一.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已经支持市面上绝大多数常见算法
    ![在这里插入图片描述](https://img-
    blog.csdnimg.cn/direct/180c7d78180b4b4c8f11e9c431babf16.png)

有一些算法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中央仓库
    ![在这里插入图片描述](https://img-
    blog.csdnimg.cn/direct/0d529d3a6bf24490927c594f675b31b8.png)

引入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());
    }
    

![在这里插入图片描述](https://img-
blog.csdnimg.cn/direct/4c639647aa34494c9c0172eac7ea2194.png)
执行代码:

  1. 可以看到bouncycastle作为加密服务提供者已经注册到java程序中
    ![在这里插入图片描述](https://img-
    blog.csdnimg.cn/direct/8409ad3e506b48a6aa38d2c53b0efbf6.png)

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

    }
}

执行结果
![在这里插入图片描述](https://img-
blog.csdnimg.cn/direct/f81919167afa441192c5ad286a4e84f3.png)

Provider NameProvider VersionAlgorithm TypeAlgorithm Name
SUN1.8AlgorithmParameterGeneratorDSA

| | AlgorithmParameters| DSA

| | CertPathBuilder| PKIX

| | CertPathValidator| PKIX

| | CertStore| Collection
LDAP
com.sun.security.IndexedCollection

| | CertificateFactory| X.509

| | Configuration| JavaLoginConfig

| | KeyFactory| DSA

| | KeyPairGenerator| DSA

| | KeyStore| CaseExactJKS
DKS
JKS

| | MessageDigest| MD2
MD5
SHA
SHA-224
SHA-256
SHA-384
SHA-512

| | Policy| JavaPolicy

| | SecureRandom| SHA1PRNG

| | Signature| NONEwithDSA
SHA1withDSA
SHA224withDSA
SHA256withDSA

SunEC| 1.8| AlgorithmParameters| EC

| | KeyAgreement| ECDH

| | KeyFactory| EC

| | KeyPairGenerator| EC

| | Signature| NONEwithECDSA
SHA1withECDSA
SHA224withECDSA
SHA256withECDSA
SHA384withECDSA
SHA512withECDSA

SunJCE| 1.8| AlgorithmParameterGenerator| DiffieHellman

| | AlgorithmParameters| AES
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

| | Cipher| AES
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

| | KeyAgreement| DiffieHellman

| | KeyFactory| DiffieHellman

| | KeyGenerator| AES
ARCFOUR
Blowfish
DES
DESede
HmacMD5
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512
RC2
SunTls12Prf
SunTlsKeyMaterial
SunTlsMasterSecret
SunTlsPrf
SunTlsRsaPremasterSecret

| | KeyPairGenerator| DiffieHellman

| | KeyStore| JCEKS

| | Mac| HmacMD5
HmacPBESHA1
HmacSHA1
HmacSHA224
HmacSHA256
HmacSHA384
HmacSHA512
PBEWithHmacSHA1
PBEWithHmacSHA224
PBEWithHmacSHA256
PBEWithHmacSHA384
PBEWithHmacSHA512
SslMacMD5
SslMacSHA1

| | SecretKeyFactory| DES
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

SunJGSS| 1.8| GssApiMechanism| 1.2.840.113554.1.2.2
1.3.6.1.5.5.2

SunJSSE| 1.8| KeyFactory| RSA

| | KeyManagerFactory| NewSunX509
SunX509

| | KeyPairGenerator| RSA

| | KeyStore| PKCS12

| | SSLContext| Default
TLS
TLSv1
TLSv1.1
TLSv1.2

| | Signature| MD2withRSA
MD5andSHA1withRSA
MD5withRSA
SHA1withRSA

| | TrustManagerFactory| PKIX
SunX509

SunMSCAPI| 1.8| Cipher| RSA
RSA/ECB/PKCS1Padding

| | KeyPairGenerator| RSA

| | KeyStore| Windows-MY
Windows-ROOT

| | SecureRandom| Windows-PRNG

| | Signature| MD2withRSA
MD5withRSA
NONEwithRSA
SHA1withRSA
SHA256withRSA
SHA384withRSA
SHA512withRSA

SunPCSC| 1.8| TerminalFactory| PC/SC

SunRsaSign| 1.8| KeyFactory| RSA

| | KeyPairGenerator| RSA

| | Signature| MD2withRSA
MD5withRSA
SHA1withRSA
SHA224withRSA
SHA256withRSA
SHA384withRSA
SHA512withRSA

SunSASL| 1.8| SaslClientFactory| CRAM-MD5
DIGEST-MD5
EXTERNAL
GSSAPI
NTLM
PLAIN

| | SaslServerFactory| CRAM-MD5
DIGEST-MD5
GSSAPI
NTLM

XMLDSig| 1.8| KeyInfoFactory| DOM

| | TransformService| http://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

| | XMLSignatureFactory| DOM

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

网络安全学习资源分享:

最后给大家分享我自己学习的一份全套的网络安全学习资料,希望对想学习 网络安全的小伙伴们有帮助!

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

【点击领取】网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。【点击领取视频教程】

在这里插入图片描述

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取技术文档】

在这里插入图片描述

(都打包成一块的了,不能一一展开,总共300多集)

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取书籍】

在这里插入图片描述

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

在这里插入图片描述

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

!(https://img-blog.csdnimg.cn/8de5365b55fd4a929e0cef43c14ce512.png)
在这里插入图片描述

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,使用 Java 加密算法对电子票进行加密签名,可以使用 Java Cryptography Architecture (JCA) 提供的 API。 一般情况下,进行加密签名的流程如下: 1. 生成密钥对。使用 KeyPairGenerator 类生成密钥对,其中包括公钥和私钥。 2. 获取待加密的数据。这里我们假设电子票已经生成并保存在一个字符串中。 3. 对待加密的数据进行加密。使用 Cipher 类对待加密的数据进行加密,其中需要指定加密算法密钥。 4. 对加密后的数据进行签名使用 Signature 类对加密后的数据进行签名,其中需要指定签名算法和私钥。 5. 将签名和加密后的数据返回。 下面是一个简单的示例代码: ```java import java.security.*; import javax.crypto.*; import java.util.Base64; public class EncryptAndSign { public static void main(String[] args) throws Exception { // 生成密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); // 待加密的数据 String plainText = "电子票内容"; // 对待加密的数据进行加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encrypted = cipher.doFinal(plainText.getBytes()); // 对加密后的数据进行签名 Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(encrypted); byte[] signatureBytes = signature.sign(); // 将签名和加密后的数据返回 String encryptedText = Base64.getEncoder().encodeToString(encrypted); String signatureText = Base64.getEncoder().encodeToString(signatureBytes); System.out.println("加密后的数据:" + encryptedText); System.out.println("签名:" + signatureText); } } ``` 上面的代码使用 RSA 算法对电子票进行加密签名。具体流程如下: 1. 使用 RSA 算法生成了一个 2048 位的密钥对。 2. 将电子票内容保存在一个字符串中。 3. 使用 RSA 算法对电子票进行加密,使用公钥进行加密。 4. 使用 SHA256withRSA 算法对加密后的数据进行签名使用私钥进行签名。 5. 将加密后的数据签名分别转换为 Base64 编码的字符串,并输出。 需要注意的是,上面的示例代码只是一个简单的示例,实际应用中还需要加入异常处理、错误处理等代码。另外,使用 RSA 算法数据进行加密签名时,需要考虑密钥的管理和存储等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值