p1和p7签名的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了p1和p7签名的区别相关的知识,希望对你有一定的参考价值。
参考技术A P1签名:即裸签名,签名值中只有签名信息.p7签名:即,签名中可以带有其他的附加信息,例如签名证书信息,签名原文信息,时间戳信息等.
所以要注意,不要p7的签名,用p1的方式来验签,这样是不对的.是错误的.
1.对要签名的信息,用指定的hash算法,获取信息的hash值.
2.用私钥,对hash值进行加密,输出加密串(也就是签名值).
以上方式也就是裸签名,PKCS#1
1.对要签名的信息(也就是签名原文),用指定的hash算法,获取信息的hash值.
2.用公钥信息,解密签名值,从中获取加密的hash串,和上面获取的hash值进行对比,一致则认为验签通过,不一致则不通过.
需要注意,如果调用远程签名(比如电子签名),因为根据要签名的数据格式的不同,所以我们本地验签的时候,也要根据不同的签名方式,来进行验证(也就说,他们那边签名的时候,真正用来签名的字节数组是怎么来的)
目前常见的几种方式:(P1签名验签)
CT_HASH:告诉签名方,我这个是对签名原文hash过了的hash串,你们直接对这个值进行加密即可,不需要再hash了.
所以这种方式,我们本地验签的时候,要将原文放入进行验签,而不是hash过后的hash值(因为验签的时候,它又会hash一次)
CT_MESSAGE:即,告诉签名方,我发过去的内容,就是签名的原文.一般来说,因为签名值都是字节数组,所以签名方会根据约定的编码方式,对这个签名原文按规定的编码方式,取它的字节数组之后,进行签名
我们本地验签的时候,也要对原文做同样的操作
CT_BASE64_DATA:因为有时候,我们要签名的原文,它就是一个byte[],但是为了方便传输,一般签名方都要求接受的是一个字符串.所以就有了这种签名方式.即:我们需要对签名原文的byte[]做base64编码,签名方收到之后,再做解码,并且把解码后的byte[]进行签名.
所以我们本身验签的时候,只要传入byte[]就行.
第三方返回的签名值,一般也是签名值byte[]做base64编码后的字符串,所以我们要做base64解码,才能获取到签名值byte[].
P7签名其实也就是P1签名的基础上,附加一些其他的信息(因为P1是裸签名,只有加密串,除了本人自己,根本不知道签名证书,公钥,签名算法,签名用的hash算法,时间戳,签名原文等等信息是什么,不便于验证签名,所以就需要有P7签名作为补充,其实也就是在P1之后,在加密串的基础上,附加这些信息上去)
所以我们在itextpdf的源码上能看到,其实它做签名的时候,也就是先构建出一个要签名的字符串,然后丢给某个私钥进行签名,获得签名值,它再对这个签名值附加:证书链,时间戳等等信息,然后构建出一个P7签名,然后放入PDF文件中.
PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22]。
PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。
验证 ECDSA P-256 签名
【中文标题】验证 ECDSA P-256 签名【英文标题】:Validating a ECDSA P-256 signature 【发布时间】:2022-01-18 05:57:09 【问题描述】:最近一段时间,我一直在尝试构建一个 Java 库来解释和验证 NZ Covid Pass。在签名验证之前,我已经让代码工作得更好或更糟(这个过程中一个稍微重要的部分)。里面的代码很完整is available here,不过还是比较粗糙。
验证器本身is available here、there is an accompying test。 Technical specification for the covid pass is here。 There are is at least one relevant section.
在与另一位开发人员合作后,我认为我已经确定了解释所提供的公钥。下面的代码(删除了调试输出)。 The public key details come from here
private PublicKey extractPublicKey(PublicKeysDetails publicKeyDetails) throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException
byte[] xBytes = Base64.getDecoder().decode(publicKeyDetails.x().replace('-', '+').replace('_', '/'));
byte[] yBytes = Base64.getDecoder().decode(publicKeyDetails.y().replace('-', '+').replace('_', '/'));
BigInteger x = new BigInteger(xBytes);
BigInteger y = new BigInteger(yBytes);
ECPoint ecPoint = new ECPoint(x, y);
ECGenParameterSpec parameterSpec = new ECGenParameterSpec("secp256r1");//publicKeyDetails.crv() Should always come from the endpoint as "P-256", java wants to know exactly secp256r1, or NIST P-256
AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");//publicKeyDetails.kty() Should always come from the endpoint as "EC"
parameters.init(parameterSpec);
ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class);
ECPublicKeySpec pubSpec = new ECPublicKeySpec(ecPoint, ecParameters);
KeyFactory kf = KeyFactory.getInstance("EC");
return kf.generatePublic(pubSpec);
该错误可能存在于该文件的其他位置,但我现在非常迷茫,不知道它可能是什么。
请帮我堆栈溢出你唯一的希望?
【问题讨论】:
【参考方案1】:答案绕了几天,我的问题特别是在将字节处理成大整数。
BigInteger x = new BigInteger(xBytes);
BigInteger y = new BigInteger(yBytes);
应该是
BigInteger x = new BigInteger(1, xBytes);
BigInteger y = new BigInteger(1, yBytes);
这说明数字应该是正数。
【讨论】:
以上是关于p1和p7签名的区别的主要内容,如果未能解决你的问题,请参考以下文章