Java中使用PSS填充的签名验签工具

引入依赖


    org.bouncycastle
    bcprov-jdk15on
    1.62

签名验签工具类

import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.PSSParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Encoder;

/**
 * Description
 * 

* * @author x00482439 * @version v1.0, 2019-06-10 * @since Security SDK */ public class RSASignature { private static final Logger Logger = LoggerFactory.getLogger(RSASignature.class); /** * 签名算法 */ private static final String SIGN_ALGORITHMS = "SHA256withRSA"; private static final String SIGN_ALGORITHMS_PSS = "SHA256withRSA/PSS"; private static final String ENCODE_ALGORITHM = "SHA-256"; /** * 生成文件摘要 * * @param content 文件内容 * @param encode 字符集编码 * @return 文件摘要 */ public static String digest(String content, String encode) { try { MessageDigest messageDigest = MessageDigest.getInstance(ENCODE_ALGORITHM); messageDigest.update(content.getBytes(encode)); byte[] digestBytes = messageDigest.digest(); return new String(Base64.getEncoder().encode(digestBytes), ICommon.GBK_ENCODEING); } catch (Exception e) { Logger.error("Summary calculation failed. {}", e.getMessage()); } return null; } /** * RSA签名,结果写入签名值文件中 * * @param file 待签名文件 * @param signFile 签名值文件 * @param signKeyFile 签名私钥文件 * @param keyPassword 签名私钥口令 */ public static void sign(File file, String signFile, String signKeyFile, String keyPassword) { try { // 先解密私钥 String encrypted = new String(Files.readAllBytes(Paths.get(signKeyFile))); encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", ""); encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", ""); encrypted = encrypted.replaceAll("\\n", ""); EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.getDecoder().decode(encrypted)); PBEKeySpec keySpec = new PBEKeySpec(keyPassword.toCharArray()); // password SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName()); PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyFactory.generatePrivate(encodedKeySpec); // 开始签名 Security.addProvider(new BouncyCastleProvider()); java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS_PSS); signature.setParameter(new PSSParameterSpec(MGF1ParameterSpec.SHA256.getDigestAlgorithm(), "MGF1", MGF1ParameterSpec.SHA256, 32, 1)); signature.initSign(priKey); signature.update(Files.readAllBytes(file.toPath())); byte[] signed = signature.sign(); String signStr = new String(Base64.getEncoder().encode(signed), StandardCharsets.UTF_8); System.out.println(signStr); Files.write(Paths.get(signFile), signStr.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { Logger.error("digital signature failed", e); } } /** * RSA验签名检查 * * @param originFile 待验证文件 * @param signFile 签名值文件 * @param signCertFile 签名证书文件 * @return 是否验签成功 */ public static boolean verify(File originFile, String signFile, String signCertFile) { try { CertificateFactory fact = CertificateFactory.getInstance("X.509"); X509Certificate certificate = (X509Certificate) fact.generateCertificate(new FileInputStream(signCertFile)); PublicKey pk = certificate.getPublicKey(); byte[] keyBytes = pk.getEncoded(); String publicKey = new BASE64Encoder().encode(keyBytes); publicKey = publicKey.replaceAll("\\r?\\n", ""); byte[] encodedKey = Base64.getDecoder().decode(publicKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); Security.addProvider(new BouncyCastleProvider()); java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS_PSS); signature.setParameter(new PSSParameterSpec(MGF1ParameterSpec.SHA256.getDigestAlgorithm(), "MGF1", MGF1ParameterSpec.SHA256, 32, 1)); signature.initVerify(pubKey); signature.update(Files.readAllBytes(originFile.toPath())); String signStr = new String(Files.readAllBytes(Paths.get(signFile)), StandardCharsets.UTF_8); return signature.verify(Base64.getDecoder().decode(signStr.replaceAll("\\n", ""))); } catch (Exception e) { Logger.error("Digital signature verification failed. {}", e.getMessage()); } return false; } }

备注

如果是openssl生成的私钥,则默认为PKCS1,需要转换

PKCS1私钥转换为PKCS8

openssl pkcs8 -topk8 -inform PEM -in sign.key -outform pem -out sign2.key
mv sign2.key sign.key

转载于:https://my.oschina.net/yidao620c/blog/3096306

你可能感兴趣的:(Java中使用PSS填充的签名验签工具)