使用BouncyCastle 实现RSA常用方法

RSA 加密/解密—PKCS8 (Java与C#互通BouncyCastle) 前提: 需要调用JavaAPI进行签名/验签、加密/解密,需要使用BouncyCastle 类库进行Java与C#之间的数据互通。 加密理解点: 1:java 私钥采用的是PKCS8 ;C# 私钥采用的是PKCS1 格式 2:RSA加密 公钥加密,私钥解密或者私钥加密和公钥解密【这点和签名sign不同,sign需要私钥签名】 3:如果 java RSA加密 最后生成16进制 C#... 阅读详情

使用BouncyCastle 实现RSA常用方法

项目地址

相关openssl命令

# OpenSSL 1.1.1h  22 Sep 2020

# 生成一个3072bit的RSA私钥
openssl genpkey -algorithm RSA-PSS -pkeyopt rsa_keygen_bits:3072 -pkeyopt rsa_keygen_pubexp:65537 -pkeyopt rsa_pss_keygen_md:sha256 -pkeyopt rsa_pss_keygen_mgf1_md:sha256 -pkeyopt rsa_pss_keygen_saltlen:32 -out rsa_pss_private_3072_restricted_nopassword.pem
# 查看私钥
openssl pkey -in rsa_pss_private_3072_restricted_nopassword.pem -text
# 导出公钥
openssl pkey -in rsa_pss_private_3072_restricted_nopassword.pem -out rsa_pss_public_3072_restricted_nopassword.pem -pubout

# 生成一个口令保护的3072bit的RSA私钥 Hello@123
openssl genpkey -aes256 -algorithm RSA-PSS -pkeyopt rsa_keygen_bits:3072 -pkeyopt rsa_keygen_pubexp:65537 -pkeyopt rsa_pss_keygen_md:sha256 -pkeyopt rsa_pss_keygen_mgf1_md:sha256 -pkeyopt rsa_pss_keygen_saltlen:32 -out rsa_pss_private_3072_restricted_password.pem
# 查看私钥
openssl pkey -in rsa_pss_private_3072_restricted_password.pem -text
# 导出公钥
openssl pkey -in rsa_pss_private_3072_restricted_password.pem -out rsa_pss_public_3072_restricted_password.pem -pubout

1. 引入pom依赖

        <bouncycastle.version>1.69</bouncycastle.version>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>${bouncycastle.version}</version>
        </dependency>

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>${bouncycastle.version}</version>
        </dependency>

2. RSA 常用方法

  • encrypt 加密
  • decrypt 解密
  • signature 签名
  • verify 验签
  • decodeEncryptedPrivateKey 从文件加载口令保护的私钥
  • decodePrivateKey 从文件加载私钥(无口令保护)
  • decodePublicKey 从文件加载公钥
  • decodePublicKey2 从文件加载公钥2
package com.ysx.utils.crypto.rsa;

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.bouncycastle.util.io.pem.PemObject;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.FileReader;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2021/7/20 23:29
 * @blog https://blog.youkuaiyun.com/next_second
 * @github https://github.com/YoungBear
 * @description 使用BouncyCastle RSA 工具类
 * 参考:https://www.baeldung.com/java-read-pem-file-keys
 */
public class RSAUtilsBC {

    /**
     * 加密算法
     */
    private static final String ENCRYPT_ALGORITHM = "RSA/None/OAEPWithSHA-256AndMGF1Padding";

    /**
     * 签名算法 SHA256withRSA 算法,PSS 填充模式
     */
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA/PSS";

    /**
     * 签名填充盐值长度
     */
    private static final int SIGNATURE_SALT_LENGTH = 32;


    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 使用公钥加密
     *
     * @param publicKey 公钥
     * @param data      待加密数据明文
     * @return 密文
     * @throws NoSuchPaddingException    异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws InvalidKeyException       异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    public static byte[] encrypt(PublicKey publicKey, byte[] data)
            throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance(ENCRYPT_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 使用私钥解密
     *
     * @param privateKey 私钥
     * @param cipherData 待解密的密文
     * @return 明文
     * @throws NoSuchPaddingException    异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws InvalidKeyException       异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    public static byte[] decrypt(PrivateKey privateKey, byte[] cipherData)
            throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance(ENCRYPT_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(cipherData);
    }

    /**
     * 签名
     *
     * @param privateKey 私钥
     * @param data       数据
     * @return 数据的签名值
     * @throws NoSuchAlgorithmException           异常
     * @throws NoSuchProviderException            异常
     * @throws InvalidAlgorithmParameterException 异常
     * @throws InvalidKeyException                异常
     * @throws SignatureException                 异常
     */
    public static byte[] signature(PrivateKey privateKey, byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, SignatureException {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        PSSParameterSpec pssParameterSpec = new PSSParameterSpec(MGF1ParameterSpec.SHA256.getDigestAlgorithm(),
                "MGF1", MGF1ParameterSpec.SHA256, SIGNATURE_SALT_LENGTH, 1);
        signature.setParameter(pssParameterSpec);
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }

    /**
     * 验签
     *
     * @param publicKey 公钥
     * @param data      数据
     * @param sign      签名值
     * @return 验签是否成功
     * @throws NoSuchAlgorithmException           异常
     * @throws NoSuchProviderException            异常
     * @throws InvalidAlgorithmParameterException 异常
     * @throws InvalidKeyException                异常
     * @throws SignatureException                 异常
     */
    public static boolean verify(PublicKey publicKey, byte[] data, byte[] sign) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, SignatureException {
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
        PSSParameterSpec pssParameterSpec = new PSSParameterSpec(MGF1ParameterSpec.SHA256.getDigestAlgorithm(),
                "MGF1", MGF1ParameterSpec.SHA256, SIGNATURE_SALT_LENGTH, 1);
        signature.setParameter(pssParameterSpec);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(sign);
    }

    /**
     * 从文件加载口令保护的私钥
     *
     * @param filePath 私钥文件路径
     * @param password 口令
     * @return 私钥
     * @throws IOException               异常
     * @throws OperatorCreationException 异常
     * @throws PKCSException             异常
     */
    public static PrivateKey decodeEncryptedPrivateKey(String filePath, String password) throws IOException, OperatorCreationException, PKCSException {
        try (PEMParser pemParser = new PEMParser(new FileReader(filePath))) {
            Object pem = pemParser.readObject();
            if (pem instanceof PKCS8EncryptedPrivateKeyInfo) {
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter()
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME);
                PKCS8EncryptedPrivateKeyInfo keyInfo = (PKCS8EncryptedPrivateKeyInfo) pem;
                InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder()
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME)
                        .build(password.toCharArray());
                return converter.getPrivateKey(keyInfo.decryptPrivateKeyInfo(pkcs8Prov));
            }
            throw new RuntimeException("invalid key file.");
        }
    }


    /**
     * 从文件加载私钥(无口令保护)
     *
     * @param filePath 私钥文件路径
     * @return 私钥
     * @throws IOException 异常
     */
    public static PrivateKey decodePrivateKey(String filePath) throws IOException {
        try (PEMParser pemParser = new PEMParser(new FileReader(filePath))) {
            Object pem = pemParser.readObject();
            if (pem instanceof PrivateKeyInfo) {
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter()
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME);
                PrivateKeyInfo keyInfo = (PrivateKeyInfo) pem;
                return converter.getPrivateKey(keyInfo);
            }
            throw new RuntimeException("invalid key file.");
        }
    }

    /**
     * 从文件加载公钥
     *
     * @param filePath 公钥文件路径
     * @return 私钥
     * @throws IOException 异常
     */
    public static PublicKey decodePublicKey(String filePath) throws IOException {
        try (PEMParser pemParser = new PEMParser(new FileReader(filePath))) {
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter()
                    .setProvider(BouncyCastleProvider.PROVIDER_NAME);
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
            return converter.getPublicKey(publicKeyInfo);
        }
    }

    /**
     * 从文件加载公钥2
     *
     * @param filePath 公钥文件路径
     * @return 公钥
     * @throws IOException              异常
     * @throws NoSuchAlgorithmException 异常
     * @throws InvalidKeySpecException  异常
     * @throws NoSuchProviderException  异常
     */
    public static PublicKey decodePublicKey2(String filePath) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
        try (PEMParser pemParser = new PEMParser(new FileReader(filePath))) {
            PemObject pemObject = pemParser.readPemObject();
            byte[] content = pemObject.getContent();
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
            KeyFactory factory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME);
            return factory.generatePublic(pubKeySpec);
        }
    }

}

3. 测试类

package com.ysx.utils.crypto.rsa;

import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCSException;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2021/7/20 23:48
 * @blog https://blog.youkuaiyun.com/next_second
 * @github https://github.com/YoungBear
 * @description
 */
public class RSAUtilsBCTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtilsBCTest.class);

    private static final String BASE_PATH = RSAUtilsBCTest.class.getResource("/openssl/").getPath();

    @Test
    public void encryptTest() throws IOException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
        String publicKeyFilePath = BASE_PATH + "rsa_pss_public_3072_restricted_password.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey(publicKeyFilePath);
        byte[] data = "London2012".getBytes(StandardCharsets.UTF_8);
        byte[] cipherData = RSAUtilsBC.encrypt(publicKey, data);
        String cipherDataHexString = Hex.toHexString(cipherData);
        System.out.println("cipherDataHexString: " + cipherDataHexString);
    }

    @Test
    public void decryptTestSuccess() throws IOException, OperatorCreationException, PKCSException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
        String privateKeyFilePath = BASE_PATH + "rsa_pss_private_3072_restricted_password.pem";
        String password = "Hello@123";
        PrivateKey privateKey = RSAUtilsBC.decodeEncryptedPrivateKey(privateKeyFilePath, password);
        String cipherDataHexString = "5ae58323930a9f0dac220483dba7e2dd1da4d56ebbfc458ff64eae0f1df599db0f3c4438e280108f1e443071efc3012b30b75a0aea565fe89d876da4d32f3574538c5410fd86531ec402775f1d3574343d726add0da44fc14b18716c4e4b2a4fc309036813b75ba5863515c394b1280ab9b94b26b576a7880c094f39bd25821992c7fd28271986eab957515458419014c1890c82a9c814bbc6eef0006fed23f62ea2a2e0f7a30cfaf5873f66267c4032e14773f2b965d9d66ad9ca492a8b847c59f454b6795d24456f288bb7420b8f5e62b34057057f339c01af5460f21e2f73dd1f90a8559b0bfbc8bea0003dcb0d9c1cda7b7f8fa169d636ddc1584d94b48bf0cfcd2f369fa3ce959ef3478b034c7253e738a7ac6b6cd999d57f7451752aa8fc6afdec6a1451b00eaef540f340c5a65d2b9084c3ad70d1e7dcf5b8847a14c7c1d2c92cf6f220d881582c7a5f5a03cba436223c5b0d4eb4b5fbc1357c477b435a16d9eb54ac9373c675ff50dc36b6b626547fe7930e8ec08676613787fcd7df";
        byte[] cipherData = Hex.decode(cipherDataHexString);
        byte[] plainData = RSAUtilsBC.decrypt(privateKey, cipherData);
        String plainText = new String(plainData, StandardCharsets.UTF_8);
        Assert.assertEquals("London2012", plainText);
    }

    @Test
    public void decryptTestFailed() throws IOException, OperatorCreationException, PKCSException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, NoSuchProviderException, InvalidKeyException {
        String privateKeyFilePath = BASE_PATH + "rsa_pss_private_3072_restricted_password.pem";
        String password = "Hello@123";
        PrivateKey privateKey = RSAUtilsBC.decodeEncryptedPrivateKey(privateKeyFilePath, password);
        String cipherDataHexString = "5ae58323930a9f0dac220483dba7e2dd1da4d56ebbfc458ff64eae0f1df599db0f3c4438e280108f1e443071efc3012b30b75a0aea565fe89d876da4d32f3574538c5410fd86531ec402775f1d3574343d726add0da44fc14b18716c4e4b2a4fc309036813b75ba5863515c394b1280ab9b94b26b576a7880c094f39bd25821992c7fd28271986eab957515458419014c1890c82a9c814bbc6eef0006fed23f62ea2a2e0f7a30cfaf5873f66267c4032e14773f2b965d9d66ad9ca492a8b847c59f454b6795d24456f288bb7420b8f5e62b34057057f339c01af5460f21e2f73dd1f90a8559b0bfbc8bea0003dcb0d9c1cda7b7f8fa169d636ddc1584d94b48bf0cfcd2f369fa3ce959ef3478b034c7253e738a7ac6b6cd999d57f7451752aa8fc6afdec6a1451b00eaef540f340c5a65d2b9084c3ad70d1e7dcf5b8847a14c7c1d2c92cf6f220d881582c7a5f5a03cba436223c5b0d4eb4b5fbc1357c477b435a16d9eb54ac9373c675ff50dc36b6b626547fe7930e8ec08676613787fcd7df";
        byte[] cipherData = Hex.decode(cipherDataHexString);
        byte[] plainData = RSAUtilsBC.decrypt(privateKey, cipherData);
        String plainText = new String(plainData, StandardCharsets.UTF_8);
        Assert.assertNotEquals("London2013", plainText);
    }

    @Test
    public void signAndVerifyTest() throws IOException, OperatorCreationException, PKCSException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException {
        String privateKeyFilePath = BASE_PATH + "rsa_pss_private_3072_restricted_password.pem";
        String password = "Hello@123";
        PrivateKey privateKey = RSAUtilsBC.decodeEncryptedPrivateKey(privateKeyFilePath, password);
        byte[] data = "Beijing2008".getBytes(StandardCharsets.UTF_8);
        byte[] signature = RSAUtilsBC.signature(privateKey, data);
        String signHexString = Hex.toHexString(signature);
        System.out.println("signHexString: " + signHexString);
    }

    @Test
    public void verifyTestSuccess() throws IOException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Beijing2008".getBytes(StandardCharsets.UTF_8);
        byte[] signature = Hex.decode("077bacf8b43da3f84b38bec809fabcf8c6dd321dde4987beca58c33fcfae7f71cfe1d0e19ec1b91802efc016da36e598e03599d6c0c6dad4209a3360d817c6119e4f8b69d342e9a263c67d03dd3212c35f34a23fcb7ae266a21f4277d0bd0d0783b6807b1f8157babc78a7ca84035029c4554e1dc843b17886d5c26d394d50be210140d40a117535a37cc20f26e93da53c52f8d112d9fbc9670fe1a08ba9753f4d204d37ffdf97f7539ddafbe95af10550b05a78a31eef9217059c556775f5bbdf88aba4ab5a30ac48989d428bb6c163910f3c34659e97b01388fb39b38c0e80b6ec69b359c30f114a9bf53253a60239d7fab2f4737af5fd9c5b15cee6c86bd65f9d89af77c93ccdf3510b9b2bb65b04020bd7570714cd230b89fb333ea0c126d59f9f40ef7e24af8bbf0eb3613e1e325251e9e6b9de2db2f19cca12b15583dfbceb56687113c8d46c4f0dbac8facde217ad2bed9c46d053d6458a64a439f6d5dbabc7e208c1e608318180882083890bd08c4dc89b9abb4084bc991901d4aaff");
        String publicKeyFilePath = BASE_PATH + "rsa_pss_public_3072_restricted_password.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey(publicKeyFilePath);
        boolean verify = RSAUtilsBC.verify(publicKey, data, signature);
        Assert.assertTrue(verify);
    }

    @Test
    public void verifyTestFailed() throws IOException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, SignatureException, NoSuchProviderException, InvalidKeyException {
        byte[] data = "Beijing2008".getBytes(StandardCharsets.UTF_8);
        byte[] signature = Hex.decode("077bacf8b43da3f84b38bec809fabcf8c6dd321dde4987be");
        String publicKeyFilePath = BASE_PATH + "rsa_pss_public_3072_restricted_password.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey(publicKeyFilePath);
        boolean verify = RSAUtilsBC.verify(publicKey, data, signature);
        Assert.assertFalse(verify);
    }

    @Test
    public void decodeEncryptedPrivateKeyTest() throws IOException, OperatorCreationException, PKCSException {
        String filePath = BASE_PATH + "rsa_pss_private_3072_restricted_password.pem";
        String password = "Hello@123";
        PrivateKey privateKey = RSAUtilsBC.decodeEncryptedPrivateKey(filePath, password);
        String algorithm = privateKey.getAlgorithm();
        int length = ((RSAPrivateKey) privateKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }

    @Test
    public void decodePrivateKeyTest() throws IOException {
        String filePath = BASE_PATH + "rsa_pss_private_3072_restricted_nopassword.pem";
        PrivateKey privateKey = RSAUtilsBC.decodePrivateKey(filePath);
        String algorithm = privateKey.getAlgorithm();
        int length = ((RSAPrivateKey) privateKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }

    @Test
    public void decodePublicKeyTest() throws IOException {
        String filePath = BASE_PATH + "rsa_pss_public_3072_restricted_password.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey(filePath);
        String algorithm = publicKey.getAlgorithm();
        int length = ((RSAPublicKey) publicKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }

    @Test
    public void decodePublicKeyTest2() throws IOException {
        String filePath = BASE_PATH + "rsa_pss_public_3072_restricted_nopassword.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey(filePath);
        String algorithm = publicKey.getAlgorithm();
        int length = ((RSAPublicKey) publicKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }

    @Test
    public void decodePublicKey2Test() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
        String filePath = BASE_PATH + "rsa_pss_public_3072_restricted_password.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey2(filePath);
        String algorithm = publicKey.getAlgorithm();
        int length = ((RSAPublicKey) publicKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }

    @Test
    public void decodePublicKey2Test2() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
        String filePath = BASE_PATH + "rsa_pss_public_3072_restricted_nopassword.pem";
        PublicKey publicKey = RSAUtilsBC.decodePublicKey2(filePath);
        String algorithm = publicKey.getAlgorithm();
        int length = ((RSAPublicKey) publicKey).getModulus().bitLength();
        LOGGER.info("algorithm: {}, length: {}", algorithm, length);
        Assert.assertEquals("RSASSA-PSS", algorithm);
        Assert.assertEquals(3072, length);
    }
}

C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在 阅读详情

相关推荐

C#下BouncyCastle实现DES加解密

BouncyCastle真是个解密利器,有了它,各种安卓java加解密算法轻松拿下! RSA算法是非对称加密,有公钥与私钥之分,所以加密的写法也不同。https://blog.youkuaiyun.com/vola9527/article/details/77715473 此处有算法介绍,讲得很清楚。 using Org.BouncyCastle.Crypto; using Org.BouncyCastl...

2971

Java的bouncycastle密码库的RSA的加密,解密,类

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.generators.*; import org.bouncycastle.crypto.params.*; import org.bouncycastle.crypto.*; import org.bouncycastle...

a571574085的博客 7474

android(客户端)和PC(服务器端)通信RSA 加密解密

android客户端代码: package com.suning.reminder.util; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileReade

xiaoyezi_1的专栏 3980

C# 使用BouncyCastle生成RSA PEM格式公钥私钥(PKCS#1,PKCS#8)

RSA非对称加密应用

weixin_42293338的博客 2709

别再只用RSA了!手把手教你用Java BouncyCastle库实现国密SM2加解密(附完整代码)

本文详细介绍了如何使用Java BouncyCastle库实现国密SM2加解密,对比了SM2与RSA在安全性、性能和合规性方面的优势,并提供了完整的代码示例和Spring Boot集成方案。SM2作为我国自主设计的商用密码标准,适用于金融科技和政务信息化等高安全需求场景。

weixin_30374009的博客 468

Bouncy Castle 密码包的配置及使用详解

1、简述 BouncyCastle(轻量级密码术包)是一种用于 Java 平台的开放源码的轻量级密码术包;Bouncycstle 包含了大量的密码算法,其支持椭圆曲线密码算法,并提供JCE 1.2.1的实现。 2、为什么要使用BouncyCastle? 我们知道,Java标准库提供了一系列常用的哈希算法。但如果我们要用的某种算法,Java标准库没有提供怎么办? 方法一:自己写一个,难度很大; 方法二:找一个现成的第三方库,直接使用。 BouncyCastle就是一个提供了很多哈希算法和加密算法的

应无所住而生其心 3万+

.NET中使用BouncyCastle动态库实现RSA方式加密方法

最近要用.NET的技术和C++写的后台联写一个RSA加密解密程序。 具体是.NET里面实现加密,C++里面解密, 要求将字符串加密成64个字节,并且每个字节转成16进制,一共128位的16进制的字符串。 .NET中实现RSA加密我使用了java中使用的一个动态库BouncyCastle.Crypto.dll,可以到网站http://www.bouncycastle.org/csharp/ 上下

isfirst的专栏 4990

BouncyCastleProvider pom坐标.txt

<!-- 微信小程序BouncyCastleProvider,BouncyCastle是一个开源的第三方算法提供商; 提供了很多Java标准库没有提供的哈希算法和加密算法, 但使用不当易引起内存泄露 --> org.bouncycastle bcprov-jdk16 1.46

C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法...

因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密。在网上查了很久也没有很好的实现。BouncyCastle的文档少之又少。很多人可能会说,C#也是可以的,通过Biginteger开源类来实现,不过那个是有一个文章,不过他加密出来的是16进制结果的。根本不能和JAVA互通。连加密出来的都不和C#原生的加密出来的结果格式一样。所以还是没有好的解决方法。 接下来还是不断的找资料,...

weixin_30654583的博客 227

c# U盘禁用---守护进程(插入,拔出,卸载等操作)

一、简介 传统的对U盘禁用,我们多采用修改注册表的方式,详情参考:https://blog.youkuaiyun.com/qq_25372599/article/details/79815407;本文将介绍一种其他的方式–后台守护程序。其原理非常简单:当守护程序检测到U盘的插入信号,我们自动卸载U盘,致使系统无法识别U盘,达到禁用U盘的效果。 二、程序设计 2.1 变量定义 strin...

星星之火燃亮码空 2846

TS808效果器制作教程

TS808效果器制作教程 可以在立创商城购买到大部分的电阻电容和IC,音频接口,踩钉,电位器和电源接口可以去某宝看看都买得到的。链接https//pan.baidu.com/s/1QId1eIE3fJ2u5NLBSISvGA。安装过程过于繁琐,把所有元器件按照图纸焊接完成就可以调试了,祝你们成功!这是TS808经典效果器制作过程的记录。IC是JRC4558。...

qq_18948149的博客 3427

C#使用BouncyCastle来实现私钥加密,公钥解密的方法

因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密。在网上查了很久也没有很好的实现。BouncyCastle的文档少之又少。很多人可能会说,C#也是可以的,通过Biginteger开源类来实现,不过那个是有一个文章,不过他加密出来的是16进制结果的。根本不能和JAVA互通。连加密出来的都不和C#原生的加密出来的结果格式一样。所以还是没有好的解决方法。 接下来还是不断的找资料,...

坚定的走 6572

解读 2025《高质量数据集 质量评测规范》

《高质量数据集质量评测规范》为2025年数据质量评估提供标准化框架,适用于政府部门、AI企业、数据服务商等行业主体。规范以"说明文档-数据质量-模型应用"三维体系为核心:明确定义高质量数据集分类,细化各项指标要求(包括文档完整性、数据规范性、应用多样性等),并提供具体评分细则(百分制,90分达标)和计算方法。附录补充多模态数据处理细则,旨在建立可操作的质量评估标准,保障优质数据供给流通。

cdfunlove的博客 1888

c#rsa加密java解密_C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法...

using System;using System.Collections.Generic;using System.Linq;using System.Text;using Org.BouncyCastle.Asn1.Pkcs;using Org.BouncyCastle.Asn1.X509;using Org.BouncyCastle.Crypto.Generators;using Org.B...

weixin_39600510的博客 697

PCIE总线及其PCIE SWITCH的使用

PCIe总线与PCI最大的区别在工作原理上,PCIe是采用点到点的串行方式进行传输的,被称为“串行PCI”,由于采用了串行方式传输使得其工作频率可以达到2.5Ghz,大大增加了传输速率,同时采用全双工的通信方式,使得其传输速度提高了一倍,每一个PCIe总线设备与外部通信时有四根数据总线,分别有两个RX和TX,两根用于发送,两根由于接收。PCIe switch中文翻译为PCIe开关或PCIe交换机,主要作用将PCIe设备互联,PCIe switch芯片与其设备的通信协议都是PCIe;

zxm8513优快云博客 4736

go实现MQTT broker(附完整源码)

go实现MQTT broker(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 577

BouncyCastle实现SHA256withRSA与RSA-PSS验签

数字签名验签是非对称加密在开放平台、支付回调与接口安全中的基础能力,核心是用公钥校验原文与签名是否匹配。SHA256withRSA基于PKCS#1 v1.5,流程确定、兼容性好;RSA-PSS引入随机盐,安全性更现代,但对MGF1哈希、SaltLength、TrailerField等参数更敏感。实际工程中,公钥可能以PEM、DER、证书或裸RSA结构出现,解析不当会触发InvalidKeySpecException;JDK版本差异也会带来Provider与PSS参数兼容问题。BouncyCastle通过JC

weixin_28607671的博客 169

AI学习指南RAG篇(19)-API调用与集成

通过上述API调用示例,您可以方便地将RAGFlow与其他系统集成,实现数据集管理、文档处理、会话管理等功能。希望本文的介绍能帮助您更好地理解和使用RAGFlow的API。

俞兆鹏的博客 2546

关于C#的RSA加密

那么问题来了,在C#的RSA加密工具类RSACryptoServiceProvider中,并没有支持PEM格式公钥为基准的加密方法,只能用一种.net平台认可的xml字符串的公钥才能够进行加密。一般对接第三方的接口时,接口提供方如果要求以RSA方式进行加密传输,并且给了你一串字符串说是RSA加密公钥,那么该公钥一般是PEM格式文件的base64字符串表现形式。另外如果在之后加密时报长度超长之类的错误,说明需要分段加密,因为RSA的加密机制要求:待加密的字节数不能超过密钥的长度值除以 8 再减去 11。

Learn_change_myself的博客 9298

【数据集7】全球人类住区层GHSL数据详解

全球人类住区层GHSL数据详解

WW、forever的博客 2253

用Python绘制DCA曲线详解及示例代码

在这篇文章中,我们将详细解释如何使用Python绘制DCA曲线,并提供示例代码。通过使用上述的示例代码和解释,你可以自己尝试不同的投资金额、期数和增长率来绘制自定义的DCA曲线。通过运行上述代码,我们将得到一个绘制了DCA曲线的图表。该图表将显示出DCA投资策略在给定投资金额、投资期数和增长率下的投资价值随时间的变化情况。在上述代码中,我们使用一个循环来计算每个投资期的DCA曲线值。现在,我们可以使用上述函数来计算DCA曲线的值,并将其绘制成图表。最后,我们返回计算得到的DCA曲线值列表。

TechPr的博客 1410

RSA代码演示

RSA实例代码 通过上一篇的RSA算法原理了解之后,这里用一段简易的Java代码进行演示。 首先我们创建一个类,然后在main方法中通过BigInteger.probablePrime(int bitLength, Random rnd)方法生成两个素数 System.out.println(BigInteger.probablePrime(10, new Random())); System.out.println(BigInteger.probablePrime(10, new Random()))

qq_43401941的博客 945

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

java RSA密钥生成

在网上找了下RSA的密钥的创建,结果全是用java序列化PublicKey和PrivateKey来保存,就自己写了个RSA公钥和私钥的创建,及进行Base64编码后保存。 这里用到了 bcprov-jdk16-1.4.5.jar ,可以在 http://www.bouncycastle.org/ 官方主页上下载.   public static void createKeyPairs() t

fengyie007的专栏 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

NetCore 下使用RSA加密,解密;并且前端使用jsencrypt.js实现Rsa相关方法。

首先上资源 jsencrypt.js下载地址:https://github.com/travist/jsencrypt 第三方Rsa密钥生成工具:BouncyCastle.Crypto.dll,直接可以在NuGet中查找。 至于为什么用第三方工具生成密钥,是为了和jsencrypt配合。c#本身RSACryptoServiceProvider类生成的工具不能再jsencrypt中使用。 有...

weixin_30724853的博客 1043

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RSA加密及其在C#中的使用

RSA加密算法在C#中的使用

iningwei的博客 2969
上一篇: openssl常用命令 pkey
下一篇: 使用BC从文件解析RSA私钥和公钥
杨小熊的笔记
博客等级 码龄15年 125粉丝 156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值