Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java';s BouncyCastle不';不要总是验证OpenSSL ECDSA签名_Java_Openssl_Bouncycastle_Ecdsa - Fatal编程技术网

Java';s BouncyCastle不';不要总是验证OpenSSL ECDSA签名

Java';s BouncyCastle不';不要总是验证OpenSSL ECDSA签名,java,openssl,bouncycastle,ecdsa,Java,Openssl,Bouncycastle,Ecdsa,我使用OpenSSL(在C++中)对文本进行签名,但是我的Java程序并不总是验证签名的消息(五分之一的消息得到验证)。有趣的是,这并没有验证其中任何一个: 曲线名称:secp256k1 签名算法:SHA256withECDSA 私钥 431313701ec60d303fa7d027d5f1579eaa57f0e870b23e3a25876e61bed2caa3 035bcefc4a6ca257e394e82c20027db2af368474afb8917273713644f11a7cecb3

我使用OpenSSL(在C++中)对文本进行签名,但是我的Java程序并不总是验证签名的消息(五分之一的消息得到验证)。有趣的是,这并没有验证其中任何一个:

曲线名称:secp256k1 签名算法:SHA256withECDSA

私钥

431313701ec60d303fa7d027d5f1579eaa57f0e870b23e3a25876e61bed2caa3
035bcefc4a6ca257e394e82c20027db2af368474afb8917273713644f11a7cecb3
公钥

431313701ec60d303fa7d027d5f1579eaa57f0e870b23e3a25876e61bed2caa3
035bcefc4a6ca257e394e82c20027db2af368474afb8917273713644f11a7cecb3
失败

要签名的文本=
PCAX2727GRO8M6VF9VJHR1JDRQ3RDPYU6XX81000PCAX273Z8KAV5UGSIQZ3TVWGO8GG6SCH6V4912345858676729
签名=
3044022061DFF8E39F9324B0794EC2C58ABDA971898F694CA980BAF3C2A4045A9048B4412054A2FB8EF3D383FD7EEB31425DBA440E2FD20537778D4AB3725046385C7845CFF0000
成功

要签名的文本=
PCAX2727GRO8M6VF9VJHR1JDRQ3RDPYU6XX81000PCAX273Z8KAV5UGSIQZ3TVWGO8GG6SCH6V491234585867122614
签名=
3046022100F200D0FB9E86A16BD46EE2DD11F1F1F18400A436D0A5C6823001A516E975A44906FCF022100D062A60611FC0F21D81FA3140741C8B6E650FFF33D2C48AEF69A340D7C7B3CA
Java

private static final String SHA256WITH_ECDSA=“SHA256withECDSA”;
公共静态布尔isValidSignature(公钥发布,字节[]dataToVerify,字节[]签名){
试一试{
Signature sign=Signature.getInstance(SHA256WITH_ECDSA,BouncyCastleProvider.PROVIDER_NAME);
sign.initVerify(pub);
签名更新(dataToVerify);
返回签名。验证(签名);
}捕获(例外e){
log.error(“错误:+e.getMessage());
}
返回false;
}
C++

std::vector utils::crypto::sign(std::string&private_key_58,std::string&message){
auto priv_bytes=utils::base58::decode_base(private_key_58);
自动摘要=utils::crypto::sha256(消息);
自动密钥=utils::crypto::ec_new_密钥对(priv_字节);
自动签名=ECDSA_do_签名(digest.data(),digest.size(),key);
自动顺序=ECDSA大小(键);
自动顺序=(uint8_t*)calloc(顺序、大小(uint8_t));
自动顺序复制=顺序;
i2d_ECDSA_SIG(签名和复印件);
std::向量s(der,der+der_len);
返回s;
}
std::vector utils::crypto::sha256(std::string&str){
无符号字符哈希[SHA256_摘要_长度];
SHA256_CTX SHA256;
SHA256_Init(&SHA256);
SHA256_更新(&SHA256,str.c_str(),str.size());
SHA256_Final(散列和SHA256);
std::矢量数据(散列,散列+SHA256_摘要长度);
返回数据;
}
EC_密钥*utils::crypto::EC_新密钥对(std::vector&priv_字节){
EC_KEY*KEY=nullptr;
BIGNUM*priv=nullptr;
BN_CTX*CTX=nullptr;
const EC_GROUP*GROUP=nullptr;
EC_点*pub=nullptr;
key=EC_key_new_by_curve_name(NID_secp256k1);
如果(!键){
std::cerrneardups和(以及更多链接)

ASN.1 DER编码是可变大小的用于除某些非常有限的数据外的所有数据,尤其是ECDSA(或DSA)签名。
ECDSA_size
返回给定密钥可能的最大长度,但每个实际签名可能是该长度或更短,具体取决于签名中值r和s的二进制表示形式,出于您的目的,这些值基本上可以视为随机数

在实际签名短于
ECDSA_size
的情况下,您仍然对整个缓冲区进行编码并将其传递给Java;注意两个字节的零(
0000
十六进制)在您的“失败”示例的末尾,DER解码器可以忽略尾部垃圾,当我在较旧的BouncyCastle和SunEC提供程序上测试这种情况时,它实际上工作正常,但从BouncyCastle 1.54开始对我来说失败了——有一个相当明显的例外,
java.security.SignatureException:解码签名字节时出错。
--SunEC从8u121开始,其原因或异常类似于
java.security.SignatureException:签名编码无效

在对“lax”编码(包括比特币中的secp256k1签名)进行了一些成功的攻击之后,许多实现最近使DER解码更加严格——请参见和。这在“添加到DER编码解析代码的更多检查”一项中提到,尽管我没有看到任何类似的Bouncy

由于secp256k1是Certicom/X9“素数”(Fp)曲线组,其辅因子为1,其阶数非常接近基本字段大小,而基本字段大小又非常接近256位(8的倍数),因此该组中的签名将按顺序编码到最大长度(和工作长度),几乎精确到1/4(25%)一段时间;剩下的时间他们会失败


官方的最佳解决方案是在指针中使用更新后的值,此处
deru copy
,由(任意)输出
i2d*
例程,以确定编码的长度,并使用该长度。如果由于某种原因无法处理可变长度,则可以传输整个缓冲区,但在使用
2+签名[1]传递到BouncyCastle(或SunEC)之前将其截断
作为有效长度,但如果更改为大于约480位的曲线,则不会更改为有效长度;除此之外,它是不同的,而且更复杂。

哇,非常感谢!