java bouncycastle_java – 使用bouncycastle进行签名和验证签名的正确方法

我正在使用bcmail-jdk16-1.46.jar和bcprov-jdk16-1.46.jar(Bouncycastle库)来签名一个字符串,然后验证签名。

这是我的代码来签字符串:

package my.package;

import java.io.FileInputStream;

import java.security.Key;

import java.security.KeyStore;

import java.security.PrivateKey;

import java.security.Security;

import java.security.Signature;

import java.security.cert.X509Certificate;

import java.util.ArrayList;

import java.util.List;

import org.bouncycastle.cert.jcajce.JcaCertStore;

import org.bouncycastle.cms.CMSProcessableByteArray;

import org.bouncycastle.cms.CMSSignedData;

import org.bouncycastle.cms.CMSSignedDataGenerator;

import org.bouncycastle.cms.CMSTypedData;

import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.operator.ContentSigner;

import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;

import org.bouncycastle.util.Store;

import sun.misc.BASE64Encoder;

public class SignMessage {

static final String KEYSTORE_FILE = "keys/certificates.p12";

static final String KEYSTORE_INSTANCE = "PKCS12";

static final String KEYSTORE_PWD = "test";

static final String KEYSTORE_ALIAS = "Key1";

public static void main(String[] args) throws Exception {

String text = "This is a message";

Security.addProvider(new BouncyCastleProvider());

KeyStore ks = KeyStore.getInstance(KEYSTORE_INSTANCE);

ks.load(new FileInputStream(KEYSTORE_FILE), KEYSTORE_PWD.toCharArray());

Key key = ks.getKey(KEYSTORE_ALIAS, KEYSTORE_PWD.toCharArray());

//Sign

PrivateKey privKey = (PrivateKey) key;

Signature signature = Signature.getInstance("SHA1WithRSA", "BC");

signature.initSign(privKey);

signature.update(text.getBytes());

//Build CMS

X509Certificate cert = (X509Certificate) ks.getCertificate(KEYSTORE_ALIAS);

List certList = new ArrayList();

CMSTypedData msg = new CMSProcessableByteArray(signature.sign());

certList.add(cert);

Store certs = new JcaCertStore(certList);

CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privKey);

gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(sha1Signer, cert));

gen.addCertificates(certs);

CMSSignedData sigData = gen.generate(msg, false);

BASE64Encoder encoder = new BASE64Encoder();

String signedContent = encoder.encode((byte[]) sigData.getSignedContent().getContent());

System.out.println("Signed content: " + signedContent + "\n");

String envelopedData = encoder.encode(sigData.getEncoded());

System.out.println("Enveloped data: " + envelopedData);

}

}

现在,EnvelopedData输出将在此过程中用于通过以下方式验证签名:

package my.package;

import java.security.Security;

import java.security.cert.X509Certificate;

import java.util.Collection;

import java.util.Iterator;

import org.bouncycastle.cert.X509CertificateHolder;

import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;

import org.bouncycastle.cms.CMSSignedData;

import org.bouncycastle.cms.SignerInformation;

import org.bouncycastle.cms.SignerInformationStore;

import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.util.Store;

import org.bouncycastle.util.encoders.Base64;

public class VerifySignature {

public static void main(String[] args) throws Exception {

String envelopedData = "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggLQMIIC" +

"OQIEQ479uzANBgkqhkiG9w0BAQUFADCBrjEmMCQGCSqGSIb3DQEJARYXcm9zZXR0YW5ldEBtZW5k" +

"ZWxzb24uZGUxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEi" +

"MCAGA1UEChMZbWVuZGVsc29uLWUtY29tbWVyY2UgR21iSDEiMCAGA1UECxMZbWVuZGVsc29uLWUt" +

"Y29tbWVyY2UgR21iSDENMAsGA1UEAxMEbWVuZDAeFw0wNTEyMDExMzQyMTlaFw0xOTA4MTAxMzQy" +

"MTlaMIGuMSYwJAYJKoZIhvcNAQkBFhdyb3NldHRhbmV0QG1lbmRlbHNvbi5kZTELMAkGA1UEBhMC" +

"REUxDzANBgNVBAgTBkJlcmxpbjEPMA0GA1UEBxMGQmVybGluMSIwIAYDVQQKExltZW5kZWxzb24t" +

"ZS1jb21tZXJjZSBHbWJIMSIwIAYDVQQLExltZW5kZWxzb24tZS1jb21tZXJjZSBHbWJIMQ0wCwYD" +

"VQQDEwRtZW5kMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+X1g6JvbdwJI6mQMNT41GcycH" +

"UbwCFWKJ4qHDaHffz3n4h+uQJJoQvc8yLTCfnl109GB0yL2Y5YQtTohOS9IwyyMWBhh77WJtCN8r" +

"dOfD2DW17877te+NlpugRvg6eOH6np9Vn3RZODVxxTyyJ8pI8VMnn13YeyMMw7VVaEO5hQIDAQAB" +

"MA0GCSqGSIb3DQEBBQUAA4GBALwOIc/rWMAANdEh/GgO/DSkVMwxM5UBr3TkYbLU/5jg0Lwj3Y++" +

"KhumYSrxnYewSLqK+JXA4Os9NJ+b3eZRZnnYQ9eKeUZgdE/QP9XE04y8WL6ZHLB4sDnmsgVaTU+p" +

"0lFyH0Te9NyPBG0J88109CXKdXCTSN5gq0S1CfYn0staAAAxggG9MIIBuQIBATCBtzCBrjEmMCQG" +

"CSqGSIb3DQEJARYXcm9zZXR0YW5ldEBtZW5kZWxzb24uZGUxCzAJBgNVBAYTAkRFMQ8wDQYDVQQI" +

"EwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEiMCAGA1UEChMZbWVuZGVsc29uLWUtY29tbWVyY2Ug" +

"R21iSDEiMCAGA1UECxMZbWVuZGVsc29uLWUtY29tbWVyY2UgR21iSDENMAsGA1UEAxMEbWVuZAIE" +

"Q479uzAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUx" +

"DxcNMTMwNTIxMDE1MDUzWjAjBgkqhkiG9w0BCQQxFgQU8mE6gw6iudxLUc9379lWK0lUSWcwDQYJ" +

"KoZIhvcNAQEBBQAEgYB5mVhqJu1iX9nUqfqk7hTYJb1lR/hQiCaxruEuInkuVTglYuyzivZjAR54" +

"zx7Cfm5lkcRyyxQ35ztqoq/V5JzBa+dYkisKcHGptJX3CbmmDIa1s65mEye4eLS4MTBvXCNCUTb9" +

"STYSWvr4VPenN80mbpqSS6JpVxjM0gF3QTAhHwAAAAAAAA==";

Security.addProvider(new BouncyCastleProvider());

CMSSignedData cms = new CMSSignedData(Base64.decode(envelopedData.getBytes()));

Store store = cms.getCertificates();

SignerInformationStore signers = cms.getSignerInfos();

Collection c = signers.getSigners();

Iterator it = c.iterator();

while (it.hasNext()) {

SignerInformation signer = (SignerInformation) it.next();

Collection certCollection = store.getMatches(signer.getSID());

Iterator certIt = certCollection.iterator();

X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();

X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);

if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert))) {

System.out.println("verified");

}

}

}

}

一切都很好,直到signer.verify(..)由于以下异常:

Exception in thread "main" org.bouncycastle.cms.CMSSignerDigestMismatchException: message-digest attribute value does not match calculated value

at org.bouncycastle.cms.SignerInformation.doVerify(Unknown Source)

at org.bouncycastle.cms.SignerInformation.verify(Unknown Source)

at my.package.VerifySignature.main(VerifySignature.java:64)

我真的不知道我做错了什么有人可以给我一个发生什么的提示吗?

PS。如果有人想测试上面的代码,你将需要我使用的测试证书文件来复制所有这些,只需从这里下载/保存:

提前致谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

来看一场 AI 重建的 3D 全息世界杯比赛!

世界杯来了!央视名嘴白岩松调侃 “俄罗斯世界杯,中国除了足球队没去,其他的都去了”,这届世界杯,中国球迷购买球票的数量在所有国家中排名第 9,可见球迷对世界杯的热情。那么,除了准备好小龙虾在…

杨中科.NET5视频教程更新了:DI、配置系统、Logging、EF Core等

我的.NET5视频教程又更新了一些内容了,包含依赖注入、配置系统、日志系统以及部分Entity Framework Core的内容。Entity Framework Core还没全讲完,会继续更新。已经有.NET Core开发经验的朋友,可以直接看配置系统第4、5节,讲了自…

编译Linux 2.6内核

编译内核易如反掌。让人叹为观止的是,这实际上比编译和安装像glibc这样的系统级组伴还要简单。2.6内核提供了一套新工具,使编译内核更加容易,比早期发布的内核有了长足的进步。 2.3.1 配置内核 因为Linux源码随手可得,那就意味着在…

获取父线程 java_java子线程中获取父线程的threadLocal中的值

我们都知道线程本地变量表也就是ThreadLocal在我们做线程级的数据隔离时非常好用,但是有时候我们会想如何让子线程获取到父线程的ThreadLocal,其实在线程中除了ThreadLocal外还有InheritableThreadLocal,顾名思义,可继承的线程变量…

源码分享,送你一份Google Python class源码

几年前,Google推出Python课堂。Google Python课堂:https://developers.google.com/edu/python/小编也整理了一下Google Python课堂的源码,里面有四个例子。logpuzzle这个例子主要是利用urllib模块做一个图片拼接的小游戏,主要是从一大堆的网页里面解析分…

用YARP当网关

Yarp是微软开源的一个用.net实现的反向代理工具包,github库就叫reverse-proxy(反向代理)(吐槽一下微软起名字233333)nuget包preview9之前都叫Microsoft.ReverseProxy,preview10变成Yarp.ReverseProxy了放上…

nginx 反向代理+ip智能解析

ocation / { if ($request_uri ~ ^/refresh.do$) { proxy_pass http://edtnew; break; 一 } if ($request_method POST) { proxy_pass http://edtold; break; 二 …

yum java 1.7_centos通过yum安装jdk1.7或1.8

今天安装elasticsearch的时候提示which: no1、 检查系统是否自带有jdk[rootnetpc.com.cn software]# rpm -qa |grep java[rootnetpc.com.cn software]# rpm -qa |grep jdk[rootnetpc.com.cn software]# rpm -qa |grep gcj如果有信息输出则需要卸载掉原来的jdk版本,用…

从生物神经网络到人工神经网络

如今提及人工智能,大家期待的一定是某种可以“学习”的方法,这种方法使用数学模型从数据中获取模式的某种表示。在众多“学习”方法中,获得最多关注,承载最多期望的非“神经网络”莫属。既然我们将这种数学方法称作神经网络&#…

很遗憾,我们正在逐渐丧失专注阅读的能力

这是头哥侃码的第238篇原创最近生活没什么规律,睡得晚,起得早,似乎除了工作之外,其余所有的节奏都有点乱了。前几天去体检,没想到像我这样的 “老司机”,居然会忘记 “要空腹” 的规定,愣是在体…

socket案例一

编写一个网络应用程序,有客户端与服务器端;当客户端向服务器端发送请求时,客户端输出服务器端返回的字符串。 回顾下socket的开发步骤: 1) 建立Socket连接 2) 获得输入/输出流 3)读/写数据 4) 关闭输入/输出流 5) 关闭…

java成员变量垃圾回收_JAVA 对象被垃圾回收后其成员变量可用吗? | 学步园

我们知道JVM中一个对象实例超出作用域或无引用的时候会被垃圾回收,那么他被垃圾回收后,依赖其成员变量的其他实例是否还能正常使用呢?经过测试后发现即使一个实例被垃圾回收,如果他内部的数据被其他对象使用,是不受影响…

陶哲轩的10岁与30岁

Terence Tao(陶哲轩),1975年7月17日出生于澳大利亚Adelaide(阿德莱德)。本讲话作于1985年上半年,即陶哲轩尚未满10周岁时所作,一个稚气儿童,给大学生和教授们作报告,少见…

NET问答: 重写了 Equals,还有必要重写 GetHashCode 吗?

咨询区 David Basarab:直入主题,参考如下代码:public class Foo {public int FooId { get; set; }public string FooName { get; set; }public override bool Equals(object obj){Foo fooItem obj as Foo;if (fooItem null) {return false;…

【转载】DataKeyNames,DataKeys 用法浅谈

原文地址:http://www.cnblogs.com/amos/archive/2010/07/16/1778796.htmlDataKeyNames作为GridView中的一个属性,我们可以利用这个属性结合DataKeys方便的访问GridView中每个字段的值。先说怎么用DataKeyNames可以直接在GridView属性中设置,多…

如果编程替换成中文就会怎样? 程序员看了表示头疼

首先大概的看一下中文编码:你以为会写中文就会编程吗?这就像你以为会写汉字就会写出好文章一样。编程是和机器沟通,因此要用机器的语言而不是人类的语言。最早的程序就是0和1的数字,不是中文也不是英文。以前的程序员,…

java new 面试_java面试30问

第一,谈谈final, finally, finalize的区别。第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?第三,Static Nested Class 和 Inner Class的不同,说得越…

使用visio 2016 绘制画UML时序图(Sequence Diagram)

什么是时序图?时序图(Sequence Diagram),又名序列图、循序图,是一种UML交互图。它通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作。让我们来看一看Visio2016对时序图的的解释。时序图的元素我们在画时序图时会涉及到7种元素&…

网页颜色搭配

兼职请上猪八戒网站转载于:https://blog.51cto.com/ayyzddq/598474

数字化诗人:这可能是第一位用算法写诗的诺贝尔文学奖得主

一位英国教授发现,一些优秀的诗人早在20世纪60年代就开始使用编码算法来写诗了。著名作家J.M.Coetzee,在早期的英国超级计算机上开发了创作诗歌的软件当我们回顾历史上探索科技应用的人才时,通常不会想到英语教授。但是伦敦国王学院现代文学博…