前言:
P1签名:即裸签名,签名值中只有签名信息.
p7签名:即,签名中可以带有其他的附加信息,例如签名证书信息,签名原文信息,时间戳信息等.
所以要注意,不要p7的签名,用p1的方式来验签,这样是不对的.是错误的.

数字签名中,包含了两个过程:
1.对要签名的信息,用指定的hash算法,获取信息的hash值.
2.用私钥,对hash值进行加密,输出加密串(也就是签名值).
以上方式也就是裸签名,PKCS#1

验证签名:
1.对要签名的信息(也就是签名原文),用指定的hash算法,获取信息的hash值.
2.用公钥信息,解密签名值,从中获取加密的hash串,和上面获取的hash值进行对比,一致则认为验签通过,不一致则不通过.

需要注意,如果调用远程签名(比如电子签名),因为根据要签名的数据格式的不同,所以我们本地验签的时候,也要根据不同的签名方式,来进行验证(也就说,他们那边签名的时候,真正用来签名的字节数组是怎么来的)

目前常见的几种方式:(P1签名验签)

contentType==CT_MESSAGE时,为待签名的消息;
contentType==CT_BASE64_DATA时,为待签名的base64编码数据;
contentType==CT_HASH时为待签名的HASH;
contentType==CT_FILE_URL时为待签名文件地址URL
contentType== CT_STORAGE时为待签名内容存储编号

CT_HASH:告诉签名方,我这个是对签名原文hash过了的hash串,你们直接对这个值进行加密即可,不需要再hash了.
所以这种方式,我们本地验签的时候,要将原文放入进行验签,而不是hash过后的hash值(因为验签的时候,它又会hash一次)

  /*** 测试hash方式的签名验签* @throws Exception */@Testpublic void testSignWithHash() {try {CertificateFactory cf = CertificateFactory.getInstance("X.509");  Certificate usercert = cf.generateCertificate(new FileInputStream(USER_CERT)); PublicKey publicKey = usercert.getPublicKey();//读取pfx证书上的秘钥对信息BouncyCastleProvider provider = new BouncyCastleProvider();Signature signature = Signature.getInstance("SHA1withRSA"); MessageDigest digest = MessageDigest.getInstance("SHA-1", provider);List<UserInfo> userInfoList = userInfoService.findAll();UserInfo userInfo = userInfoList.get(0);Map<String, Object> puserCert = new HashMap<>();puserCert.put("userInfo", userInfo);List<UserCert> userCertList = userCertService.getListByParam(puserCert);UserCert userCert = userCertList.get(0);YuanZi_P1SignRequest yuanZiP1SignRequest = new YuanZi_P1SignRequest();yuanZiP1SignRequest.setAlias(userInfo.getAlias());yuanZiP1SignRequest.setHashAlg("SHA1");yuanZiP1SignRequest.setContentType("CT_HASH");String content = "我是签名原文";byte[] dataToSign = digest.digest(content.getBytes(Charset.forName("UTF-8")));System.out.println("dataToSign:"+Base64.encodeBytes(dataToSign));yuanZiP1SignRequest.setContent(Base64.encodeBytes(dataToSign));YuanZi_P1SignResponse yuanZiP1SignResponse = yuanZiService.signP1(yuanZiP1SignRequest);System.out.println("原子服务返回的签名值:"+yuanZiP1SignResponse.getSignedData());byte[] dataHadSignature = Base64.decode(yuanZiP1SignResponse.getSignedData());YuanZi_VerifyP1SignRequest yuanZiVerifyP1SignRequest = new YuanZi_VerifyP1SignRequest();yuanZiVerifyP1SignRequest.setSignedData(yuanZiP1SignResponse.getSignedData());yuanZiVerifyP1SignRequest.setContentType("CT_HASH");yuanZiVerifyP1SignRequest.setContent(Base64.encodeBytes(dataToSign));yuanZiVerifyP1SignRequest.setHashAlg("SHA1");yuanZiVerifyP1SignRequest.setCert(userCert.getCertBuf().getCertsignBuf());YuanZi_VerifyP1SignResponse yuanZiVerifyP1SignResponse = yuanZiService.verifyP1Sign(yuanZiVerifyP1SignRequest);System.out.println(yuanZiVerifyP1SignResponse.getCode());//本地验签boolean verify=false;  signature.initVerify(usercert);  //使用公钥初始化签名对象,用于验证签名  signature.update(content.getBytes(Charset.forName("UTF-8")));verify= signature.verify(dataHadSignature); //得到验证结果  System.out.println("本地的验签结果:"+verify);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}

CT_MESSAGE:即,告诉签名方,我发过去的内容,就是签名的原文.一般来说,因为签名值都是字节数组,所以签名方会根据约定的编码方式,对这个签名原文按规定的编码方式,取它的字节数组之后,进行签名

我们本地验签的时候,也要对原文做同样的操作

 /*** 测试原子服务P1方式的签名和验签通过* @throws Exception */@Testpublic void testSign_P1_CT_MESSAGE() {try {CertificateFactory cf = CertificateFactory.getInstance("X.509");  Certificate usercert = cf.generateCertificate(new FileInputStream(USER_CERT)); PublicKey publicKey = usercert.getPublicKey();//读取pfx证书上的秘钥对信息BouncyCastleProvider provider = new BouncyCastleProvider();Signature signature = Signature.getInstance("SHA1withRSA"); MessageDigest digest = MessageDigest.getInstance("SHA-1", provider);List<UserInfo> userInfoList = userInfoService.findAll();UserInfo userInfo = userInfoList.get(0);Map<String, Object> puserCert = new HashMap<>();puserCert.put("userInfo", userInfo);List<UserCert> userCertList = userCertService.getListByParam(puserCert);UserCert userCert = userCertList.get(0);YuanZi_P1SignRequest yuanZiP1SignRequest = new YuanZi_P1SignRequest();yuanZiP1SignRequest.setAlias(userInfo.getAlias());yuanZiP1SignRequest.setHashAlg("SHA1");yuanZiP1SignRequest.setContentType("CT_MESSAGE");String content = "我是签名原文";yuanZiP1SignRequest.setContent(content);YuanZi_P1SignResponse yuanZiP1SignResponse = yuanZiService.signP1(yuanZiP1SignRequest);System.out.println("原子服务返回的签名值:"+yuanZiP1SignResponse.getSignedData());byte[] dataHadSignature = Base64.decode(yuanZiP1SignResponse.getSignedData());YuanZi_VerifyP1SignRequest yuanZiVerifyP1SignRequest = new YuanZi_VerifyP1SignRequest();yuanZiVerifyP1SignRequest.setSignedData(yuanZiP1SignResponse.getSignedData());yuanZiVerifyP1SignRequest.setContentType("CT_MESSAGE");yuanZiVerifyP1SignRequest.setContent(content);yuanZiVerifyP1SignRequest.setHashAlg("SHA1");yuanZiVerifyP1SignRequest.setCert(userCert.getCertBuf().getCertsignBuf());YuanZi_VerifyP1SignResponse yuanZiVerifyP1SignResponse = yuanZiService.verifyP1Sign(yuanZiVerifyP1SignRequest);System.out.println(yuanZiVerifyP1SignResponse.getCode());//本地验签boolean verify=false;  signature.initVerify(usercert);  //使用公钥初始化签名对象,用于验证签名  signature.update(content.getBytes(Charset.forName("UTF-8")));verify= signature.verify(dataHadSignature); //得到验证结果  System.out.println("本地的验签结果:"+verify);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}

CT_BASE64_DATA:因为有时候,我们要签名的原文,它就是一个byte[],但是为了方便传输,一般签名方都要求接受的是一个字符串.所以就有了这种签名方式.即:我们需要对签名原文的byte[]做base64编码,签名方收到之后,再做解码,并且把解码后的byte[]进行签名.
所以我们本身验签的时候,只要传入byte[]就行.
第三方返回的签名值,一般也是签名值byte[]做base64编码后的字符串,所以我们要做base64解码,才能获取到签名值byte[].

/*** 测试原子服务P1方式的CT_BASE64_DATA签名和验签通过* @throws Exception * * 注意多种签名方式,你传给它要签名的数据,和它最后执行签名的时候,真正要签的那个原文可能跟你传的不是同一个(比如需要做String 转为byte,base64编码要解码)*/@Testpublic void testSign_P1_CT_BASE64_DATA() {try {CertificateFactory cf = CertificateFactory.getInstance("X.509");  Certificate usercert = cf.generateCertificate(new FileInputStream(USER_CERT)); PublicKey publicKey = usercert.getPublicKey();//读取pfx证书上的秘钥对信息BouncyCastleProvider provider = new BouncyCastleProvider();Signature signature = Signature.getInstance("SHA1withRSA"); MessageDigest digest = MessageDigest.getInstance("SHA-1", provider);List<UserInfo> userInfoList = userInfoService.findAll();UserInfo userInfo = userInfoList.get(0);Map<String, Object> puserCert = new HashMap<>();puserCert.put("userInfo", userInfo);List<UserCert> userCertList = userCertService.getListByParam(puserCert);UserCert userCert = userCertList.get(0);YuanZi_P1SignRequest yuanZiP1SignRequest = new YuanZi_P1SignRequest();yuanZiP1SignRequest.setAlias(userInfo.getAlias());yuanZiP1SignRequest.setHashAlg("SHA1");yuanZiP1SignRequest.setContentType("CT_BASE64_DATA");byte[] dataToSign = new byte[10];String base64ToSign = Base64.encodeBytes(dataToSign);yuanZiP1SignRequest.setContent(base64ToSign);YuanZi_P1SignResponse yuanZiP1SignResponse = yuanZiService.signP1(yuanZiP1SignRequest);System.out.println("原子服务返回的签名状态:"+yuanZiP1SignResponse.getCode());System.out.println("原子服务返回的签名值:"+yuanZiP1SignResponse.getSignedData());//签名后的byte[] dataHadSignature = Base64.decode(yuanZiP1SignResponse.getSignedData());YuanZi_VerifyP1SignRequest yuanZiVerifyP1SignRequest = new YuanZi_VerifyP1SignRequest();yuanZiVerifyP1SignRequest.setSignedData(yuanZiP1SignResponse.getSignedData());yuanZiVerifyP1SignRequest.setContentType("CT_BASE64_DATA");yuanZiVerifyP1SignRequest.setContent(base64ToSign);yuanZiVerifyP1SignRequest.setHashAlg("SHA1");yuanZiVerifyP1SignRequest.setCert(userCert.getCertBuf().getCertsignBuf());YuanZi_VerifyP1SignResponse yuanZiVerifyP1SignResponse = yuanZiService.verifyP1Sign(yuanZiVerifyP1SignRequest);System.out.println(yuanZiVerifyP1SignResponse.getCode());System.out.println(yuanZiVerifyP1SignResponse.getMessage());//本地验签boolean verify=false;  signature.initVerify(publicKey);  //使用公钥初始化签名对象,用于验证签名  //原子signature.update(dataToSign);verify= signature.verify(dataHadSignature); //得到验证结果  System.out.println("本地的验签结果:"+verify);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}

P7签名:
P7签名其实也就是P1签名的基础上,附加一些其他的信息(因为P1是裸签名,只有加密串,除了本人自己,根本不知道签名证书,公钥,签名算法,签名用的hash算法,时间戳,签名原文等等信息是什么,不便于验证签名,所以就需要有P7签名作为补充,其实也就是在P1之后,在加密串的基础上,附加这些信息上去)

补充:
因为P7签名值包含签名证书,原文等信息,所以发送到服务器验签的时候,只需要把签名值发给服务器即可,而p1,是裸签名,发送到服务器验证的时候,需要签名证书,签名值,和原文三个参数才能验证

所以我们在itextpdf的源码上能看到,其实它做签名的时候,也就是先构建出一个要签名的字符串,然后丢给某个私钥进行签名,获得签名值,它再对这个签名值附加:证书链,时间戳等等信息,然后构建出一个P7签名,然后放入PDF文件中.

PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22]。
PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。

p1和p7签名的区别相关推荐

  1. CFCA签章中p1和p7签名的区别

    前言: P1签名:即裸签名,签名值中只有签名信息. p7签名:即,签名中可以带有其他的附加信息,例如签名证书信息,签名原文信息,时间戳信息等. 所以要注意,不要p7的签名,用p1的方式来验签,这样是不 ...

  2. 从P1到P7——我在淘宝这7年

    从P1到P7--我在淘宝这7年 作者: 赵超  发布时间: 2012-02-25 14:47  阅读: 159999 次  推荐: 217   [收藏]   (一) 2011-12-08 [原文链接] ...

  3. OV代码签名和EV代码签名证书区别

    原文来自:OV代码签名和EV代码签名证书区别_代码签名证书_Gworg 如果代码分发在网络上,则可能会受到侵害.代码可能会在到达用户前被黑客攻击.被其他开发人员盗用,或者因为"身份不明的发布 ...

  4. 群签名和环签名的区别_苹果企业签名和苹果超级签名的区别

    iPhone使用的用户越来越多,现在苹果APP的签名业务也逐渐成熟,苹果签名可以解决APP上架问题上架APP非常的漫长并且非常的严格,现在除了苹果企业签名还有了苹果超级签名,不过这两种签名之间又有什么 ...

  5. 群签名和环签名的区别_Monero技术详解(三):核心技术—环签名(1)

    在前文介绍了Monero的一次性地址方案.从方案看来,Monero中的UTXO只有一次性地址,用户地址是产生一次性地址的基础,用户对UTXO的所有权并不能显现地看出来.发送人在每次交易时创建一次性地址 ...

  6. 群签名和环签名的区别_环签名,聚合签名

    本文主要对当下的一些密码学技术的简单阐述 参考文献: 环签名 环签名(ring signature)是一种数字签名方案,最初由Rivest等人提出,环签名是一种简化的群签名,环签名中只有环成员没有管理 ...

  7. 从P1到P7——我在淘宝这7年(转)

    作者: 赵超  发布时间: 2012-02-25 14:47  阅读: 114607 次  推荐: 153   [收藏] (一) 2011-12-08 [原文链接] 今天有同事恭喜我,我才知道自己在淘 ...

  8. (转)从P1到P7——我在淘宝这7年

    (一) 2011-12-08 [原文链接] 今天有同事恭喜我,我才知道自己在淘宝已经七周年了.很多人第一句话就是七年痒不痒,老实说,也曾经痒过,但往往都是一痒而过,又投入到水深火热的工作中去.回家之后 ...

  9. 从P1到P7——我在淘宝这7年转载

    转自:http://kb.cnblogs.com/page/132752/ (一) 2011-12-08 [原文链接] 今天有同事恭喜我,我才知道自己在淘宝已经七周年了.很多人第一句话就是七年痒不痒, ...

最新文章

  1. 数据挖掘十大算法--Apriori算法
  2. php正则表达式正向预查,javascript正则表达式-----正向预查
  3. wgn和awgn函数
  4. LeetCode——分治
  5. unity3d模拟树叶飘动_Unity3D独立游戏开发日记(一):动态生成树木
  6. Spring和JSF集成:MVC螺母和螺栓
  7. 低压抽屉柜常见故障处理方法_低压配电设备常见故障分析,处理办法介绍
  8. (JAVA)Object类之Scanner
  9. 香甜的黄油(信息学奥赛一本通-T1345)
  10. javascript 使用drop元素实现拖动(ondragstart、ondrag、 ondragend、ondragenter,ondragover、ondragleave、ondrop )
  11. 软件工程--概要设计
  12. Java使用thumbnailator批量压缩JPG图片、加水印
  13. Solving environment: failed
  14. 群晖 winscp php,WinSCP自动执行脚本
  15. 工具及方法 - 查询IP信息
  16. 【if 的高阶用法练习题】if only / I wish
  17. 一阶系统开环传递函数表达式_机械振动理论(2)-多自由度系统
  18. 学计算机等级考试电脑版软件,猎证全国计算机等级考试学习系统
  19. js getElementById().innerHTML和getElementById().value区别
  20. 中琅条码打印软件之如何导出条形码或二维码矢量文件到Coredraw

热门文章

  1. 剖析 Promise 之基础篇
  2. Java多线程系列(六):深入详解Synchronized同步锁的底层实现
  3. 论文浅尝 | 利用知识-意识阅读器改进的不完整知识图谱问答方法
  4. 科普 | “开放知识”的定义
  5. 连接MySql出现异常解决:java.sql.SQLException: The server time zone value is unrecognized or represents。
  6. 消息队列---消息模型及使用场景
  7. 1.15-1.16 sqoop action
  8. 算法训练 Pollution Solution(计算几何)
  9. NodeJs系列二:你好,世界
  10. C#表格文字多收缩样式