- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我必须验证证书。我不是密码学专家,所以可能我做错了什么(或所有事情 :) )。当代码到达最后一步时 (boolean b = sig.verify(CertSign);
),它会引发异常:java.security.SignatureException:错误解码签名字节。有人可以帮我弄清楚我做错了什么吗?
以下是显示问题的测试代码:
private void test() {
byte [] CertBody = new byte[]{(byte)0x7F,(byte)0x4E,(byte)0x81,(byte)0x82,
(byte)0x5F,(byte)0x29,(byte)0x01,(byte)0x00,
(byte)0x42,(byte)0x08,(byte)0xFB,(byte)0x55,
(byte)0x54,(byte)0x4F,(byte)0x02,(byte)0xFF,
(byte)0xFF,(byte)0x01,(byte)0x5F,(byte)0x4C,
(byte)0x07,(byte)0xFF,(byte)0x53,(byte)0x4D,
(byte)0x52,(byte)0x44,(byte)0x54,(byte)0x02,
(byte)0x7F,(byte)0x49,(byte)0x4E,(byte)0x06,
(byte)0x09,(byte)0x2B,(byte)0x24,(byte)0x03,
(byte)0x03,(byte)0x02,(byte)0x08,(byte)0x01,
(byte)0x01,(byte)0x07,(byte)0x86,(byte)0x41,
(byte)0x04,(byte)0x6C,(byte)0x17,(byte)0x5B,
(byte)0xB9,(byte)0xEF,(byte)0x5D,(byte)0x02,
(byte)0x20,(byte)0x51,(byte)0xCC,(byte)0xB2,
(byte)0x89,(byte)0x09,(byte)0x42,(byte)0x15,
(byte)0x85,(byte)0xD3,(byte)0x1A,(byte)0xCD,
(byte)0xA7,(byte)0x1B,(byte)0x08,(byte)0x4A,
(byte)0x48,(byte)0x8F,(byte)0x7B,(byte)0x77,
(byte)0x5B,(byte)0x57,(byte)0x9B,(byte)0xB7,
(byte)0x41,(byte)0x3B,(byte)0xDA,(byte)0x4C,
(byte)0xDE,(byte)0x70,(byte)0x11,(byte)0x17,
(byte)0xE0,(byte)0xD9,(byte)0xD1,(byte)0x0F,
(byte)0x74,(byte)0xD6,(byte)0x25,(byte)0xB2,
(byte)0x86,(byte)0xCA,(byte)0x04,(byte)0x64,
(byte)0x54,(byte)0x4F,(byte)0x1B,(byte)0x53,
(byte)0xF3,(byte)0x24,(byte)0x02,(byte)0xD3,
(byte)0xB3,(byte)0x74,(byte)0xEF,(byte)0xA6,
(byte)0xC7,(byte)0x5F,(byte)0x20,(byte)0x08,
(byte)0xEA,(byte)0xF4,(byte)0xBE,(byte)0xCC,
(byte)0x03,(byte)0x18,(byte)0x02,(byte)0xA3,
(byte)0x5F,(byte)0x25,(byte)0x04,(byte)0x5A,
(byte)0xAF,(byte)0xA9,(byte)0xDF,(byte)0x5F,
(byte)0x24,(byte)0x04,(byte)0x5C,(byte)0x90,
(byte)0xDD,(byte)0x5F};
byte [] CertSign = new byte[]{(byte)0x3D,(byte)0x61,(byte)0x23,
(byte)0xBE,(byte)0x6C,(byte)0x0B,
(byte)0xC1,(byte)0x3E,(byte)0x7A,
(byte)0x2D,(byte)0x60,(byte)0x3D,
(byte)0x28,(byte)0xF0,(byte)0x29,
(byte)0xCC,(byte)0x8C,(byte)0x55,
(byte)0xF1,(byte)0x9A,(byte)0x5C,
(byte)0x7E,(byte)0xBE,(byte)0xFD,
(byte)0x43,(byte)0x27,(byte)0x1A,
(byte)0x9D,(byte)0xA1,(byte)0x7C,
(byte)0x81,(byte)0x09,(byte)0x5C,
(byte)0x1D,(byte)0x26,(byte)0x27,
(byte)0x76,(byte)0x73,(byte)0x74,
(byte)0x87,(byte)0xF9,(byte)0x6C,
(byte)0x2A,(byte)0xC9,(byte)0xA3,
(byte)0x32,(byte)0x3C,(byte)0x60,
(byte)0x51,(byte)0x71,(byte)0x6D,
(byte)0x2F,(byte)0xC0,(byte)0xF6,
(byte)0x89,(byte)0x14,(byte)0x93,
(byte)0xB2,(byte)0xB6,(byte)0x87,
(byte)0x21,(byte)0xAF,(byte)0x01,
(byte)0x42};
String Algorithm = "brainpoolP256r1";
byte [] PublicPoint = new byte[]{(byte)0x04,(byte)0x68,(byte)0xF8,
(byte)0xD6,(byte)0xB3,(byte)0x94,
(byte)0xD2,(byte)0x8E,(byte)0x2B,
(byte)0x4D,(byte)0xFA,(byte)0x36,
(byte)0x52,(byte)0xAE,(byte)0xAC,
(byte)0xDA,(byte)0xD3,(byte)0x19,
(byte)0x21,(byte)0xC2,(byte)0x12,
(byte)0x8D,(byte)0x58,(byte)0x9F,
(byte)0x4E,(byte)0xF1,(byte)0xB1,
(byte)0xC4,(byte)0x10,(byte)0x97,
(byte)0x29,(byte)0xDC,(byte)0xA8,
(byte)0xA1,(byte)0xC9,(byte)0x53,
(byte)0x04,(byte)0xC8,(byte)0x77,
(byte)0x4F,(byte)0x57,(byte)0xFA,
(byte)0xFB,(byte)0x15,(byte)0x59,
(byte)0xB9,(byte)0x2F,(byte)0x72,
(byte)0x6A,(byte)0xE4,(byte)0x22,
(byte)0x64,(byte)0x3E,(byte)0x1B,
(byte)0x11,(byte)0x8D,(byte)0x69,
(byte)0xAC,(byte)0x36,(byte)0x25,
(byte)0xAD,(byte)0x1C,(byte)0x30,
(byte)0x04,(byte)0xA9};
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
ECNamedCurveParameterSpec params1 = ECNamedCurveTable.getParameterSpec(Algorithm);
try {
KeyFactory fact = KeyFactory.getInstance("ECDSA", "BC");
ECCurve curve = params1.getCurve();
java.security.spec.EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, params1.getSeed());
java.security.spec.ECPoint point=ECPointUtil.decodePoint(ellipticCurve, PublicPoint);
java.security.spec.ECParameterSpec params2=EC5Util.convertSpec(ellipticCurve, params1);
java.security.spec.ECPublicKeySpec keySpec = new java.security.spec.ECPublicKeySpec(point,params2);
ECPublicKey PK = (ECPublicKey)fact.generatePublic(keySpec);
Signature sig;
sig = Signature.getInstance("ECDSA", "BC");
sig.initVerify(PK);
sig.update(CertBody);
boolean b = sig.verify(CertSign);
if (b)
{
Logger.getLogger(CardManager.class.getName()).log(Level.INFO, "verificato");
}
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException | InvalidKeyException | SignatureException ex) {
Logger.getLogger("test").log(Level.SEVERE, null, ex);
}
}
我希望 b 等于 true(或 false),但我却得到以下异常:
_java.security.SignatureException: error decoding signature bytes.
at org.bouncycastle.jcajce.provider.asymmetric.util.DSABase.engineVerify(DSABase.java:80)
at java.security.Signature$Delegate.engineVerify(Signature.java:1223)
at java.security.Signature.verify(Signature.java:656)_
最佳答案
异常原因
正如问题的评论中已经提到的,签名的长度与预期的长度不同。
异常发生了,因为 DER 编码的签名预计有 70 个字节,但您的 CertSign 只包含 64 个字节。
假设
由于它是 64 字节,因此可以假设它是一个 ECDSA 签名,由两个串联的 BigInteger 数字组成,每个数字 32 字节。
ECDSA签名转DER编码签名
要将其转换为 DER 编码签名,可以使用以下方法:
private byte[] DEREncodeSignature(byte [] signature) throws IOException {
BigInteger r = new BigInteger(1, Arrays.copyOfRange(signature, 0, 32));
BigInteger s = new BigInteger(1, Arrays.copyOfRange(signature, 32, 64));
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
}
然后需要调整代码中使用签名的行,例如像这样:
boolean b = sig.verify(DEREncodeSignature(CertSign));
if (b) {
Logger.getLogger(CardManager.class.getName()).log(Level.INFO, "verificato");
}
else {
Logger.getLogger(CardManager.class.getName()).log(Level.INFO, "controllo fallito");
}
快速测试
然后异常就消失了,调试控制台的输出是这样的:
May 11, 2019 5:09:48 PM CardManager test
INFO: controllo fallito
所以验证实际上失败了,但你提到你希望 b 为真或假,所以这可能是正确的结果。但是如果没有更多的数据,这是不可能验证的。
进一步测试
我也很快用你的代码尝试了不同的签名算法。对于他们每个人,都会得到一个错误。
String[] signatureAlgorithms = new String[] {"RIPEMD160withECDSA", "SHA224withECDDSA", "SHA256withECDDSA", "SHA384withECDDSA", "SHA512withECDDSA", "SHA1withECDSA", "NONEwithECDSA", "SHA224withECDSA", "SHA256withECDSA", "SHA384withECDSA", "SHA512withECDSA", "SHA3-224withECDSA", "SHA3-256withECDSA", "SHA3-384withECDSA", "SHA3-512withECDSA"};
for(String algorithm : signatureAlgorithms) {
Signature sig;
Logger.getLogger(CardManager.class.getName()).log(Level.INFO, "trying aloorithm " + algorithm + ": ");
sig = Signature.getInstance(algorithm, "BC");
...
仍然 - 没有进一步的数据(例如使用的签名算法等)很难说不匹配的原因是什么。
使用不同的测试数据
为了验证包括新 DEREncodeSignature 在内的例程是否正常工作,我签署了消息“Hello world!” ECDSA
生成器使用 brainpoolP256r1
参数规范和 SHA256withECDDSA
签名算法,则数据如下所示:
byte[] CertBody = new byte[]{(byte) 0x48,
(byte) 0x65, (byte) 0x6C, (byte) 0x6C,
(byte) 0x6F, (byte) 0x20, (byte) 0x77,
(byte) 0x6F, (byte) 0x72, (byte) 0x6C,
(byte) 0x64, (byte) 0x21};
byte[] CertSign = new byte[]{
(byte)0x0C,(byte)0x5B,(byte)0xE9,
(byte)0xA4,(byte)0xF7,(byte)0xC9,
(byte)0x5A,(byte)0x69,(byte)0x8E,
(byte)0x91,(byte)0x50,(byte)0xB4,
(byte)0x4E,(byte)0x33,(byte)0x14,
(byte)0x7C,(byte)0x2F,(byte)0x15,
(byte)0x93,(byte)0x97,(byte)0x8B,
(byte)0xD8,(byte)0x65,(byte)0x20,
(byte)0x1B,(byte)0x1D,(byte)0xF4,
(byte)0x8A,(byte)0xB3,(byte)0x81,
(byte)0x55,(byte)0x6A,
(byte)0x96,
(byte)0xE4,(byte)0x89,(byte)0x05,
(byte)0x80,(byte)0xAA,(byte)0x34,
(byte)0x3A,(byte)0x86,(byte)0x11,
(byte)0x5F,(byte)0x0B,(byte)0x8F,
(byte)0xF7,(byte)0xE7,(byte)0xA6,
(byte)0x7D,(byte)0xCC,(byte)0x9C,
(byte)0xD0,(byte)0xC8,(byte)0x94,
(byte)0xCA,(byte)0x78,(byte)0x9C,
(byte)0xFE,(byte)0x41,(byte)0x2A,
(byte)0xB0,(byte)0xE1,(byte)0x7E,
(byte)0x29,
};
byte[] PublicPoint = new byte[]{
(byte) 0x04,
(byte) 0x1E, (byte) 0xC8, (byte) 0xB7,
(byte) 0x00, (byte) 0xF1, (byte) 0xFD,
(byte) 0x06, (byte) 0x97, (byte) 0x73,
(byte) 0x71, (byte) 0x09, (byte) 0x12,
(byte) 0xF2, (byte) 0xB7, (byte) 0xEF,
(byte) 0xA5, (byte) 0x23, (byte) 0xA1,
(byte) 0xC1, (byte) 0x6C, (byte) 0xA7,
(byte) 0xD1, (byte) 0x0C, (byte) 0x25,
(byte) 0x6E, (byte) 0x04, (byte) 0x09,
(byte) 0x7A, (byte) 0x62, (byte) 0xC3,
(byte) 0x0E, (byte) 0x93, (byte) 0x54,
(byte) 0x7F, (byte) 0x0C, (byte) 0xE4,
(byte) 0x0F, (byte) 0xF8, (byte) 0x63,
(byte) 0x82, (byte) 0x6D, (byte) 0x0B,
(byte) 0x50, (byte) 0xC0, (byte) 0x59,
(byte) 0x1F, (byte) 0xFC, (byte) 0x36,
(byte) 0x1B, (byte) 0x0E, (byte) 0x2A,
(byte) 0xA3, (byte) 0xD4, (byte) 0x29,
(byte) 0x4E, (byte) 0x30, (byte) 0x91,
(byte) 0x44, (byte) 0x28, (byte) 0x2E,
(byte) 0x15, (byte) 0x76, (byte) 0x48,
(byte) 0xE7
};
如果获取该数据并通过例程运行,包括。 DEREncodeSignature 然后在调试控制台中显示以下输出:
May 12, 2019 12:13:42 AM CardManager test
INFO: verificato
(当然使用 sig = Signature.getInstance("SHA256withECDDSA", "BC");
)
这意味着对于 ECDSA
使用 brainpoolP256r1
参数规范和 SHA256withECDDSA
生成的数据,它将与替代测试数据一起使用。
关于签名验证期间的 Java 异常(错误解码签名字节),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55742269/
美好的一天!我试图添加两个字节变量并注意到奇怪的结果。 byte valueA = 255; byte valueB = 1; byte valueC = (byte)(valueA + valueB
嗨,我是 swift 的新手,我正在尝试解码以 [Byte] 形式发回给我的字节数组?当我尝试使用 if let string = String(bytes: d, encoding: .utf8)
我正在使用 ipv4 和 ipv6 存储在 postgres 数据库中。 因为 ipv4 需要 32 位(4 字节)而 ipv6 需要 128(16 字节)位。那么为什么在 postgres 中 CI
我很好奇为什么 Go 不提供 []byte(*string) 方法。从性能的角度来看,[]byte(string) 不会复制输入参数并增加更多成本(尽管这看起来很奇怪,因为字符串是不可变的,为什么要复
我正在尝试为UDP实现Stop-and-Wait ARQ。根据停止等待约定,我在 0 和 1 之间切换 ACK。 正确的 ACK 定义为正确的序列号(0 或 1)AND消息长度。 以下片段是我的代码的
我在下面写了一些代码,目前我正在测试,所以代码中没有数据库查询。 下面的代码显示 if(filesize($filename) != 0) 总是转到 else,即使文件不是 0 字节而是 16 字节那
我使用 Apache poi 3.8 来读取 xls 文件,但出现异常: java.io.IOException: Unable to read entire header; 0 by
字典大小为 72 字节(根据 getsizeof(dict) 在字典上调用 .clear() 之后发生了什么,当新实例化的字典返回 240 字节时? 我知道一个简单的 dict 的起始大小为“8”,并
我目前正在努力创建一个函数,它接受两个 4 字节无符号整数,并返回一个 8 字节无符号长整数。我试图将我的工作基于 this research 描述的方法,但我的所有尝试都没有成功。我正在处理的具体输
看看这个简单的程序: #include using namespace std; int main() { unsigned int i=0x3f800000; float* p=(float*)(
我创建了自己的函数,将一个字符串转换为其等效的 BCD 格式的 bytes[]。然后我将此字节发送到 DataOutputStram (使用需要 byte[] 数组的写入方法)。问题出在数字字符串“8
此分配器将在具有静态内存的嵌入式系统中使用(即,没有可用的系统堆,因此“堆”将只是“char heap[4096]”) 周围似乎有很多“小型内存分配器”,但我正在寻找能够处理非常小的分配的一个。我说的
我将数据库脚本从 64 位系统传输到 32 位系统。当我执行脚本时,出现以下错误, Warning! The maximum key length is 900 bytes. The index 'U
想知道 128 字节 ext2 和 256 字节 ext3 文件系统之间的 inode 数据结构差异。 我一直在为 ext2、128 字节 inode 使用此引用:http://www.nongnu.
我试图理解使用 MD5 哈希作为 Cassandra key 在“内存/存储消耗”方面的含义: 我的内容(在 Java 中)的 MD5 哈希 = byte[] 长 16 个字节。 (16 字节来自维基
检查其他人是否也遇到类似问题。 shell脚本中的代码: ## Convert file into Unix format first. ## THIS is IMPORTANT. ###
我们有一个测量数据处理应用程序,目前所有数据都保存为 C++ float,这意味着在我们的 x86/Windows 平台上为 32 位/4 字节。 (32 位 Windows 应用程序)。 由于精度成
我读到在 Java 中 long 类型可以提升为 float 和 double ( http://www.javatpoint.com/method-overloading-in-java )。我想问
我有一个包含 n 个十进制元素的列表,其中每个元素都是两个字节长。 可以说: x = [9000 , 5000 , 2000 , 400] 这个想法是将每个元素拆分为 MSB 和 LSB 并将其存储在
我使用以下代码进行 AES-128 加密来编码一个 16 字节的 block ,但编码值的长度给出了 2 个 32 字节的 block 。我错过了什么吗? plainEnc = AES.enc
我是一名优秀的程序员,十分优秀!