openssl在java端的加解密和签名验证

本文介绍了如何在Java环境下利用OpenSSL进行加解密操作,并详细阐述了如何进行RSA签名和验证的过程,包括openssl的下载、命令使用以及相应的Java代码实现。在实际应用中,通过PKCS#8编码转换私钥,使用sha1算法进行签名,文中还提到了去除BouncyCastleProvider后加解密速度的提升现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

 很大程度上参考:http://blog.youkuaiyun.com/chaijunkun/article/details/7275632
 在此基础上添加了签名和验证方法。为了完整性,把其前面的内容也搬过来了。

二、openssl下载

  1. windows版本下载地址:http://slproweb.com/products/Win32OpenSSL.html
  2. 绿色版下载地址:http://sourceforge.net/projects/openssl/?source=directory

三、openssl使用
绿色版bin目录下openssl.exe打开运行,有个warning,可以不用理会。
下面命令不需要打开头的“openssl”

这里写图片描述

  1. 生成私钥:openssl genrsa -out rsa_private_key.pem 1024 保存在当前文件夹下的rsa_private_key.pem文件中,以下同理。
  2. 根据私钥生成公钥:openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
  3. 此时的私钥还不能直接被java使用(但可以被openssl使用),需要进行PKCS#8编码:openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
  4. openssl生成签名文件:因为java端签名验证使用sha1算法做摘要。故openssl使用sha1签名:openssl sha1 -sign rsa_private_key.pem -out rsasign.bin tos.txt tos.txt为自己创建的需要签名的文本,里面可以随意写点字符。为了和后面代码匹配文本内容为:helloadsfdsfaasdfasffffffffffffdsafdasfasdfsafzxvxzvasfs

四、代码参考—— jdk1.5

cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());

改为

cipher = Cipher.getInstance("RSA");

本机运行时,起初加解密太慢,去掉BouncyCastleProvider后速度明显提升。而且加密结果一致,不明所以啊(可能和jdk版本有关)。

DEFAULT_PUBLIC_KEY 为rsa_public_key.pem内容。(去掉空格和换行符,头尾的—–PUBLIC KEY—–)
DEFAULT_PRIVATE_KEY 内容为pkcs8_rsa_private_key.pem的内容,格式处理同上。

package com.haiyisoft.lwsp.dto.login;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import sun.misc.BASE64Decoder;

/**
 * 生成私钥:openssl genrsa -out rsa_private_key.pem 1024 
 * 根据私钥生成公钥:openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
 * 私钥还不能直接被使用,需要进行PKCS#8编码:openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt 
 * sha1签名 openssl sha1 -sign rsa_private_key.pem -out rsasign.bin tos.txt 
 * pkcs8_rsa_private_key 私钥
 * java可以使用
 */
public class RsaEncrypt {
   

    // openssl 产生的钥 私钥为pkcs8形式
    private final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxrbbBo9Zkd4uQ16/cx0LJwUJpUHAYHRnSwM8uPgoRkPEXXRFR9sWvZ3WAFdjSB/3KSd8LAK34P8sq49BouUxCJw0h6o2uv0wKIy70k3mTc4KVF12iClPfZR1fQ3FmJrOPr35AiuZTz+YsMp24WageIVz3VZ7qYmzMZ8dH0Ez+ZQIDAQAB";

    private final String DEFAULT_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALGttsGj1mR3i5DXr9zHQsnBQmlQcBgdGdLAzy4+ChGQ8RddEVH2xa9ndYAV2NIH/cpJ3wsArfg/yyrj0Gi5TEInDSHqja6/TAojLvSTeZNzgpUXXaIKU99lHV9DcWYms4+vfkCK5lPP5iwynbhZqB4hXPdVnupibMxnx0fQTP5lAgMBAAECgYBkxQH+pt4kEszb9Afwri5J4Mq6kf1RH8gSiHm4X0U0m0CxIH5/Pvb1OTch0sIqtI+Sl/zg75y7S+r9Q0Fi85y0ghkbLFmmZgv8bGzh4k34WWFCyPMRmexOhsi+IGpTOYkbRnJbycxuY0TXJHHYvEcS0I14fUvI8gbflf12l6DCwQJBANoPXAjHF4TQm0h+qTyFmB4NoGlV3DNH2yk2D2UlKJ+9o7YqjMmw/jNQyeNb65Dj62ij57FQrbn4yfHLBWlkxnECQQDQl7g4kNtDzh0eMMcZYVKU7W/eEkd/G8WeldH26RWE1kZzYBIHeQJiujASDFodM3pqbJ3ssOCizoN1Acy+LPk1AkBvBXjvQyZXSbp1238gwEflrTxpxPw646/SuKJ39cZMJkpu2hUaL1INIGnZpxg1icV2XlT9cz
可以以下代码来读取 OpenSSL 生成的 AES 256 密钥: ```java import java.io.BufferedReader; import java.io.FileReader; import java.security.Key; import java.security.KeyFactory; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class ReadOpenSSLPrivateKey { public static void main(String[] args) throws Exception { // 读取私钥文件 BufferedReader br = new BufferedReader(new FileReader("private_key.pem")); String line; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { if (line.startsWith("-----BEGIN ") || line.startsWith("-----END ")) { continue; } sb.append(line); } br.close(); // 解码 Base64 格式的密钥 byte[] keyBytes = Base64.getDecoder().decode(sb.toString()); // 获取密码 String password = "your_password"; // 生成 AES 密钥 byte[] ivBytes = new byte[16]; byte[] saltBytes = Arrays.copyOfRange(keyBytes, 8, 16); byte[] keyBytesWithoutSalt = Arrays.copyOfRange(keyBytes, 16, keyBytes.length); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); SecretKeySpec keySpec = new SecretKeySpec(getAESKey(password, saltBytes), "AES"); // 解密私钥 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] decryptedBytes = cipher.doFinal(keyBytesWithoutSalt); // 转换成 Key 对象 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decryptedBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); Key privateKey = kf.generatePrivate(spec); System.out.println(privateKey); } public static byte[] getAESKey(String password, byte[] saltBytes) throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, 65536, 256); SecretKey tmp = factory.generateSecret(spec); return tmp.getEncoded(); } } ``` 其中 `private_key.pem` 是 OpenSSL 生成的密钥文件,`your_password` 是生成密钥时设置的密码。这段代码会读取密钥文件,解码 Base64 格式的密钥,生成 AES 密钥,解密私钥,并将其转换成 Java 的 `Key` 对象。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值