Bouncycastle1.60实现加解密、密钥存储、签名验签

1 版本概述

    原来项目中使用的是Bouncycastle1.46版本的,后由于项目需要,改成了1.60版本。本文基于1.60版本实现加密解密、本地存储、签名验签功能。本文代码已上线稳定运行,现整理干货如下。首先在项目中添加如下依赖:

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

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcpkix-jdk15on</artifactId>
  <version>1.60</version>
</dependency>

2 代码实现

    编写加解密工具类,直接贴代码了(包含测试代码),略显粗糙,读者可优化该工具类GmUtil,详见生成密钥:generateKeyPair、加密:sm2Encrypt、解密sm2Decrypt等方法:3 密钥存储实现

   若需要存储密钥,则上述生成的KeyPair对象无法存在特定的文件或数据库中,我们需要将其转化成字符串型的数据,方式如下:

/*
 *
 *KeyPair密钥转String型密钥
 */
public static List<String> getStringKey(KeyPair keyPair){
    // 公钥转换
    PublicKey publicKey = keyPair.getPublic();
    BCECPublicKey localECPublicKEy = (BCECPublicKey)publicKey;
    ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(localECPublicKEy.getQ(),ecDomainParameters);
    byte[] publicKeyByte = ecPublicKeyParameters.getQ().getEncoded(false);
    String publicKeyStr = TransferUtil.byteToHex(publicKeyByte);
    PrivateKey privateKey = keyPair.getPrivate();
    BCECPrivateKey bcecPrivateKey = (BCECPrivateKey)privateKey;
    BigInteger privateKeyBI = bcecPrivateKey.getD();
    byte[] privateKeyByte = TransferUtil.biConvert32Bytes(privateKeyBI);
    String privateKeyStr = TransferUtil.byteToHex(privateKeyByte);

    System.out.println("公钥: "+publicKeyStr);
    System.out.println("私钥: "+privateKeyStr);
    List<String> keyPairList = new ArrayList<>(2);
    // 公私钥字符串存入list
    byte[] temp = TransferUtil.hexToByte(privateKeyStr);

    keyPairList.add(publicKeyStr);
    keyPairList.add(privateKeyStr);
    return keyPairList;
}

/*
 *
 *用String型公钥加密
 */
private static String encrypt(String data,String pubKey){
    //构造ECPoint
    ECPoint ecPoint = SM2Util.CURVE.decodePoint(TransferUtil.hexStringToBytes(pubKey));
    ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(ecPoint,GmUtil.ecDomainParameters);
    SM2Engine sm2Engine = new SM2Engine();
    sm2Engine.init(true,new ParametersWithRandom(ecPublicKeyParameters,new SecureRandom()));
    byte[] byteResult;
    try{
        byte[] byteData = data.getBytes();
        byte[] temp = sm2Engine.processBlock(byteData,0,byteData.length);
        byteResult = changeC1C2C3ToC1C3C2(temp);
    }catch (InvalidCipherTextException e){
        throw new RuntimeException(e);
    }
    return Hex.toHexString(byteResult);
}

/*
 *
 *用String私钥解密
 */
private static String decrypt(String encryptedData,String privateKey){
    byte[] priKeyByte = TransferUtil.hexToByte(privateKey);
    ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1,priKeyByte),ecDomainParameters);
    SM2Engine sm2Engine = new SM2Engine();
    sm2Engine.init(false,ecPrivateKeyParameters);
    byte[] result = null;
    try{
        byte[] encryptDataByte = TransferUtil.hexToByte(encryptedData);
        byte[] temp = changeC1C3C2ToC1C2C3(encryptDataByte);
        result = sm2Engine.processBlock(temp,0,temp.length);
    }catch (Exception e){
        e.printStackTrace();
    }
    return new String(result);
}

4 测试加解密:

//生成公私钥
KeyPair kp = generateKeyPair();
Lisy<String> keys = getStringKey(kp);
//加解密测试
String pub = "0471569510119CB9182D757942A36A61F052E155FCB795956445D33ACBA8972F0CAF47DDE468D48D7080640244C1BBC46199AFB88C974F6020B590B3DA5C1FBA00";
String pri = "8D704AE2D67CBF865224ADA883FE9F32D6CAFDEEC9A7E9D9999010856F71C2FB";
String temp = encrypt("hello world!",pub);
System.out.println("加密后的数据: "+temp);
System.out.println("解密出的数据: "+decrypt(temp,pri));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
BouncyCastle 是 Java 平台上的一个加解密库,支持多种加密算法,包括 PGP 加解密。以下是使用 BouncyCastle 实现 PGP 加密解密文件的示例代码: 1. 加载 BouncyCastle Provider: ``` Security.addProvider(new BouncyCastleProvider()); ``` 2. 生成 PGP 密钥对: ``` PGPKeyPairGenerator kpg = new JcaPGPKeyPairGenerator().setProvider("BC").setAlgorithm(AsymmetricAlgorithmTags.RSA_GENERAL).setKeySize(2048); PGPKeyPair kp = kpg.generate(); ``` 3. 导出公钥和私钥: ``` PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(kp.getPublicKey().getEncoded(), new JcaKeyFingerprintCalculator()); PGPPublicKey publicKey = publicKeyRing.getPublicKey(); PGPPrivateKey privateKey = kp.getPrivateKey(); ``` 4. 加密文件: ``` // 创建加密器 PGPEncryptorBuilder builder = new JcePGPEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256).setSecureRandom(new SecureRandom()); builder.setProvider("BC"); PGPEncryptor encryptor = builder.build(publicKey); // 创建输出流 File outputFile = new File("encrypted.pgp"); OutputStream outputStream = new FileOutputStream(outputFile); // 创建压缩器 PGPCompressedDataGenerator compressor = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP); OutputStream compressedOutputStream = compressor.open(outputStream); // 创建签名器 PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(PublicKeyAlgorithmTags.RSA_GENERAL, HashAlgorithmTags.SHA256).setProvider("BC")); signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey); signatureGenerator.generateOnePassVersion(false).encode(compressedOutputStream); // 创建字节流加密器 PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator(); OutputStream literalOutputStream = literalDataGenerator.open(compressedOutputStream, PGPLiteralData.BINARY, "filename", new Date(), new byte[1024]); // 加密文件内容 File inputFile = new File("input.txt"); InputStream inputStream = new FileInputStream(inputFile); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { literalOutputStream.write(buffer, 0, length); } inputStream.close(); // 关闭流 literalDataGenerator.close(); signatureGenerator.generate().encode(compressedOutputStream); compressor.close(); encryptor.close(); outputStream.close(); ``` 5. 解密文件: ``` // 创建解密器 PGPObjectFactory factory = new JcaPGPObjectFactory(new FileInputStream("encrypted.pgp")); PGPEncryptedDataList encryptedDataList = (PGPEncryptedDataList) factory.nextObject(); PGPPBEEncryptedData pbeEncryptedData = (PGPPBEEncryptedData) encryptedDataList.get(0); PGPPrivateKey privateKey = findPrivateKey("userid", "password".toCharArray()); InputStream decryptedInputStream = pbeEncryptedData.getDataStream(new JcePBEDataDecryptorFactoryBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(privateKey)); // 创建签名校验器 PGPObjectFactory plainFactory = new JcaPGPObjectFactory(decryptedInputStream); PGPOnePassSignatureList signatureList = (PGPOnePassSignatureList) plainFactory.nextObject(); PGPOnePassSignature signature = signatureList.get(0); PGPPublicKey publicKey = findPublicKey(signature.getKeyID()); signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey); PGPLiteralData literalData = (PGPLiteralData) plainFactory.nextObject(); InputStream literalInputStream = literalData.getInputStream(); // 校验签名 byte[] buffer = new byte[1024]; int length; while ((length = literalInputStream.read(buffer)) != -1) { signature.update(buffer, 0, length); } if (signature.verify(((PGPSignatureList) plainFactory.nextObject()).get(0))) { System.out.println("Signature verified"); } else { System.out.println("Signature not verified"); } // 读取文件内容 while ((length = literalInputStream.read(buffer)) != -1) { // 处理文件内容 } literalInputStream.close(); decryptedInputStream.close(); ``` 其中,`findPrivateKey` 和 `findPublicKey` 方法根据指定的用户 ID 查找对应的私钥和公钥。在实际使用时,需要将用户 ID 和密钥信息存储在合适的位置,例如文件或数据库中,然后在程序中进行读取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值