赞
踩
笔者在做 RSA 签名时,遇到了一个异常,详见下文。
14:04:33.622 [main] ERROR com.test.util.SignUtil - NoSuchAlgorithmException
java.security.NoSuchAlgorithmException: SHA256WithRSAandMGF1 Signature not available
at java.security.Signature.getInstance(Signature.java:229)
at com.test.util.SignUtil.signData(SignUtil.java:29)
at com.test.util.SignUtil.main(SignUtil.java:49)
以下是做签名的 Java 代码。
package com.test.util; import lombok.extern.slf4j.Slf4j; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; @Slf4j public class SignUtil { /** * RSA signature 私钥签名 * * @param data data to be signed * @param privateKeystr privatekey * @param signMode 签名模式 * @return signature result */ public static String signData(String data, String privateKeystr, String signMode) { try { Base64.Decoder decoder = Base64.getDecoder(); byte[] keyBytes = decoder.decode(privateKeystr); PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keyspec); Signature signature = Signature.getInstance(signMode); signature.initSign(privateKey); signature.update(data.getBytes(StandardCharsets.UTF_8)); byte[] mi = signature.sign(); Base64.Encoder encoder = Base64.getEncoder(); return encoder.encodeToString(mi); } catch (NoSuchAlgorithmException e) { log.error("NoSuchAlgorithmException", e); } catch (InvalidKeyException e) { log.error("InvalidKeyException", e); } catch (InvalidKeySpecException e) { log.error("InvalidKeySpecException", e); } catch (SignatureException e) { log.error("SignatureException", e); } return null; } public static void main(String[] args) { String data = "sssssaaaaaaa"; String signCnt = signData(data, "MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCeRbxjAYEXpef+/iRdiWzPguqTTZdFljVHW0x/S6uFzXlVRNDoGmcXrFJ39j5C6pLSNnfLnDUb/xioa5hlDXBj0BgAJErwOx8obxnsbvtzqok8OAqYRGC9RRoIxkdmvrKjzI9FouhkbTFRVJFA26bNltVrtUkrAllOTeRIisudC8MgeFuqR/7PK/BbgFtzeX62396lO6aaOgqyM6XD183bDeXyANZj2FqpOLw2a5wcEJdJdiF+SPj7g/Ba+PvIInhHOH/811e4qFy+T3JVZGIoq4NZlxE5KbnM1KPdGVsi8p9PZSoq9p8ijwFfMFWF89wo7a7+zKZ4Nu4MfS4Q1wKnRHLIhzBIIHOtBbtJN76n9UNExg597dSN//f2qDvDiHHTsI7BV9RxcMJVuDyNbufCh79gjdDm9zp+vTQZNnIsl50wwp6HmIztojmDcv9sBjFUuq8cFYH3/+54WYerNgiIn1MRsv09IcAtsHKdn1v/VAL8xWTH8COxTMfGg4TZQ9UM675+3qUKzy12QXa726+OMInRmrg8grAP8JctRX1uV55cs2a302RHozSobaa2KCmqTyOttRjNV3wSD/5PRVVOeP1qHxLUmKxHSqVX+qIaTK7cE742yRd5lCuAcswJWCkW8U5QpUw4rS6BwEhOQjuSEEyn5Iu7LIoINSbXZHgwCwIDAQABAoICABn//riM8LX/zSK4gSTUhIl6Siq0nlsSF+KG/wQSXDT40ivNyDu4yqK67jlCvGuluUTLKdbK7HaS62wPcNN457Od5bNwQtc//xhXV/zdJnWT2EOKOUNWSEYPaf1zBRu9y/7Yhdi8sEx/G5DuwYXUD4zKcHjnKQPluOICLbQ1CMnduspEu1o3xYYnA68kYOGRXd2Q3TRrnizLyCIKFfscIncPy2x78rwoOIyAA3s1Jkn997xbqZjjR/OZcwyexk3US8n3YB8bCRAOqF2jE3cvrGhd9I/tHykyz5D0hY62saAGF2Gljs3MAcxdja4jdIkyzEH0+cBlwhsRev2WOtENYSPzGXcoWs95IJdZl3ryewAp9SR7acfWahUPahC74baKhcdnf97QAHpMqIAc7Miq/mWha033fHdk7oC/j4kuKO8fvWA541Q3FSDGPDz6JQT5rehYxUuIiiDxYGl72zdgooA719eeu9gVOuqiXOHl3GqTdvmwlnqfOwPezW5rOxjH+5mWVOHaGvGPw5sP2RctKxDYY4Phbk+LvroKqZ83NPot35T/JJC2Id7hQTu3vcEbdNZu4oIBWem1RQ0igtTSdt08brTwCuA2vtjx682yyBN5TvokXsq/7ATGkJ5h6WCrkp4yezt7ynKJJjJdUA5gfl7zMC4OG8WTrzhQaUPDBIDBAoIBAQDLN7FuBF1ukCHt3OKrGbubeol/jrWqr2W6dC8OdBmJFHexJbGmwW9ltsMhV4hIqnRIrnE53OJW5KFItiXP0mxiLeY2WCxp2KFWQYw3X1XGbsVuOZt5UGaI8RCRafbgmSQ+PVjevOZSPq3kHcap6K3aNjERffCfBkXpPRN7vUrI8hfCq+rwJR91g3xmUWMMS2BUtkQOrzt5oSlvQWZs6G6vupvOgmpASrR0VvhfCvy0XvfFRcXmhImP3JuAcIGMEaB8RX68lLO7QxxwXQVWRMBPtC3Om2x+4lmmoDrBLvcTkGj3NYqWN0stkQGSdhVXpiqr/dK6Q8gDuPyd10IW/VGRAoIBAQDHYY7Ny1UU5rfjQDZ4Vq0sDPcvJHFe66AszkxVei72LbV4RTIgR5lXyIvZmI7VIRbk7FSbFp5kjv0gZ3x3vetHisewMOfMj99n9KfNrGCoyu3fqCS708AVIfTUaquKCUQsxSxIu0E93LeNYJSA+cB6GJMGaMkzBRd0cPEfzrCZscs3eKGOmwjp+NqHZOgLyHoO5OelMDcncNNardr9k66AzaqSlLIkLs8UCoLOm+T8YI1zWZSV2G+982RPKZGtAIk+BAad/bfR+MwZwOOhOzMNtWcwC770TROxHQMmFi9+NHtx9ExV/bZLVSFcm33QREje4iKU0Ckyf9FXpFNt6FnbAoIBAQCIMMXfNlurajri32KlSnSZqVCWxPxo7G1fvNeAdzxZyvbAKMPbPs26O/af1LrIADw4LXhCUA78LvML+M50bdAnKB2dlBAHy5+sX/dpcKHaf4ge68qPTdu5sNzqpzpFoTxR3ek+NRiiS9FcDLyESCSjFihiUaW93YVi34S8K8r/yocz9uVXlXl01u6635Ziue1QOGp58OQKCoDrR8gt+sObT5N1nZ85gRdY1KRVhdZ/xxmEAtOzPmW2nSE1vbCEP5fvUN+z4HBncn2PrDeUbjT39YexbCYVDvsIGV/m8eOyH9jIvAAp1dqzKfgEwNBi0kDMzSm5nQ1huUrLOWTYZWKRAoIBACQHkinIO7jKNKLBYNaAO00Bjs2bFU2k4M4X/Z1YthHQksGIJ5XDuocte3A37F/BWgTGXEemX7smR8HKUajFzjWgc5N4UvsZaLK9eHFnXBREj5XiKbkze7uV5ktYd2U7ZXF9tBH0nMaUEyteL5fbChhGRpNa7jjlC6cEHd60mB8+DM4aY3+ErqixSrQ63N/8O2pjnSSxwNXEwrzZPACk5lzqTY+thT+aodsqRxcU/t1IiWc14e7uLMszp4XSqjuMJEDrs1JrngM4pZFl1Py22PP6OwpopPo6z3srFf2U9sIks8YU8pJ7hay5Vo0IoES5gj2cuckQkNFKXccrr9PlsA8CggEBAMGXlS/ja5MVT6zfXZAAEfreksHejtZ6v8g32JuShigZ7DkLXICjLRwZ2ui3SnK0akTNk/9Lc8UyDu/9GZwDoRa2HFCHRA4kmfAKSZDzr2h4Epi/Qym6QVj9rswbR8m17d4Fuo5weq/qvs91JkxBVBVNcypY2dUlBNsFJX0extQ//GjOidGPKDF+A9eqBS0gvMu3n+YBhQyPPhovq3nDhu/eQRN56uukE80PoMSDH29wMCwulf5cx2WLI8EuL5yLtrc3cUGhGz1kOLOim6fBLJ6htnK/QKmWGpcvZB0ervQ5t4h1/WS1bkzNFJszN4bWTL99MLJJwNw2kqnwUtZySLE=", "SHA256WithRSAandMGF1"); System.out.println(signCnt); } }
SHA256WithRSAandMGF1 是 BC Provider 提供的一个签名算法,而 JDK 1.8 的 java.security.* 包中并没有这个 Provider。运行如下代码,可以打印 JDK 中的 Provider 列表,以及所有签名算法。
public static void main(String[] args) { TreeSet<String> algorithms = new TreeSet<>(); Provider[] providers = Security.getProviders(); System.out.println("-----Provider 列表如下:-----"); for (Provider provider : providers) { System.out.println(provider.getName()); } System.out.println("-----支持的签名算法如下:-----"); for (Provider provider : providers) { for (Provider.Service service : provider.getServices()) if (service.getType().equals("Signature")) { algorithms.add(service.getAlgorithm()); } } for (String algorithm : algorithms) { System.out.println(algorithm); } }
运行结果如下所示:
-----Provider 列表如下:----- SUN SunRsaSign SunEC SunJSSE SunJCE SunJGSS SunSASL XMLDSig SunPCSC Apple -----支持的签名算法如下:----- MD2withRSA MD5andSHA1withRSA MD5withRSA NONEwithDSA NONEwithECDSA SHA1withDSA SHA1withECDSA SHA1withRSA SHA224withDSA SHA224withECDSA SHA224withRSA SHA256withDSA SHA256withECDSA SHA256withRSA SHA384withECDSA SHA384withRSA SHA512withECDSA SHA512withRSA
由结果可见,SHA256WithRSAandMGF1 签名算法确实不支持。
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
static {
Security.addProvider(new BouncyCastleProvider());
}
再次运行第三章中的代码,最新输出如下所示。
-----Provider 列表如下:----- SUN SunRsaSign SunEC SunJSSE SunJCE SunJGSS SunSASL XMLDSig SunPCSC Apple BC -----支持的签名算法如下:----- 1.2.840.113549.1.1.10 DDSA DETDSA DSA DSTU4145 ECDDSA ECDSA ECGOST3410 ECGOST3410-2012-256 ECGOST3410-2012-512 GOST3410 GOST3411-2012-256WITHECGOST3410-2012-256 GOST3411-2012-512WITHECGOST3410-2012-512 GOST3411WITHDSTU4145 GOST3411WITHDSTU4145LE GOST3411WITHECGOST3410 MD2WITHRSA MD2withRSA MD4WITHRSA MD5WITHRSA MD5WITHRSA/ISO9796-2 MD5andSHA1withRSA MD5withRSA NONEWITHDSA NONEwithDSA NONEwithECDSA OID.1.2.840.113549.1.1.10 RAWRSASSA-PSS RIPEMD128WITHRSA RIPEMD128WITHRSA/X9.31 RIPEMD160WITHECDSA RIPEMD160WITHPLAIN-ECDSA RIPEMD160WITHRSA RIPEMD160WITHRSA/X9.31 RIPEMD160withRSA/ISO9796-2 RIPEMD256WITHRSA RMD128WITHRSA RMD128WITHRSA/X9.31 RMD160WITHRSA RMD160WITHRSA/X9.31 RMD256WITHRSA RSA RSASSA-PSS SHA1WITHCVC-ECDSA SHA1WITHDDSA SHA1WITHDETDSA SHA1WITHECDDSA SHA1WITHECNR SHA1WITHPLAIN-ECDSA SHA1WITHRSA SHA1WITHRSA/ISO9796-2 SHA1WITHRSA/X9.31 SHA1WITHRSAANDMGF1 SHA1withDSA SHA1withECDSA SHA1withRSA SHA224WITHCVC-ECDSA SHA224WITHDDSA SHA224WITHDETDSA SHA224WITHDSA SHA224WITHECDDSA SHA224WITHECDSA SHA224WITHECNR SHA224WITHPLAIN-ECDSA SHA224WITHRSA SHA224WITHRSA/ISO9796-2 SHA224WITHRSA/X9.31 SHA224WITHRSAANDMGF1 SHA224withDSA SHA224withECDSA SHA224withRSA SHA256WITHCVC-ECDSA SHA256WITHDDSA SHA256WITHDETDSA SHA256WITHDSA SHA256WITHECDDSA SHA256WITHECDSA SHA256WITHECNR SHA256WITHPLAIN-ECDSA SHA256WITHRSA SHA256WITHRSA/ISO9796-2 SHA256WITHRSA/X9.31 SHA256WITHRSAANDMGF1 SHA256withDSA SHA256withECDSA SHA256withRSA SHA3-224WITHDDSA SHA3-224WITHDSA SHA3-224WITHECDDSA SHA3-224WITHECDSA SHA3-224WITHRSA SHA3-224WITHRSAANDMGF1 SHA3-256WITHDDSA SHA3-256WITHDSA SHA3-256WITHECDDSA SHA3-256WITHECDSA SHA3-256WITHRSA SHA3-256WITHRSAANDMGF1 SHA3-384WITHDDSA SHA3-384WITHDSA SHA3-384WITHECDDSA SHA3-384WITHECDSA SHA3-384WITHRSA SHA3-384WITHRSAANDMGF1 SHA3-512WITHDDSA SHA3-512WITHDSA SHA3-512WITHECDDSA SHA3-512WITHECDSA SHA3-512WITHRSA SHA3-512WITHRSAANDMGF1 SHA384WITHCVC-ECDSA SHA384WITHDDSA SHA384WITHDETDSA SHA384WITHDSA SHA384WITHECDDSA SHA384WITHECDSA SHA384WITHECNR SHA384WITHPLAIN-ECDSA SHA384WITHRSA SHA384WITHRSA/ISO9796-2 SHA384WITHRSA/X9.31 SHA384WITHRSAANDMGF1 SHA384withECDSA SHA384withRSA SHA512(224)WITHRSA SHA512(224)WITHRSA/ISO9796-2 SHA512(224)WITHRSA/X9.31 SHA512(224)WITHRSAANDMGF1 SHA512(256)WITHRSA SHA512(256)WITHRSA/ISO9796-2 SHA512(256)WITHRSA/X9.31 SHA512(256)WITHRSAANDMGF1 SHA512WITHCVC-ECDSA SHA512WITHDDSA SHA512WITHDETDSA SHA512WITHDSA SHA512WITHECDDSA SHA512WITHECDSA SHA512WITHECNR SHA512WITHPLAIN-ECDSA SHA512WITHRSA SHA512WITHRSA/ISO9796-2 SHA512WITHRSA/X9.31 SHA512WITHRSAANDMGF1 SHA512withECDSA SHA512withRSA SM3WITHSM2 WhirlpoolWITHRSA/ISO9796-2 WhirlpoolWITHRSA/X9.31
可以看到,BC Provider 已经被添加到列表中,且 SHA256WithRSAandMGF1 算法也在支持的签名算法列表中。
再次运行签名方法,异常问题已经被修复,能正确对数据进行签名。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。