我試圖導入C++使用OpenSSL ECDSA公鑰(用於驗證簽名),但d2i_ECPKParameters返回NULL。進口WebCrypto產生ECDSA公共密鑰驗證操作
使用Web Cryptographi API生成的密鑰;在spki格式(W3 TR doc在導出密鑰時談論ASN.1結構,以及在spki中使用DER編碼時)導出的公鑰。
我是新來的OpenSSL,我做錯了什麼?
導入:
bool ecdsa_verify(
const std::array<uint8_t, 20>& hash,
const std::experimental::basic_string_view<uint8_t>& signature,
const std::experimental::basic_string_view<uint8_t>& public_key) {
EC_GROUP* ec_group = nullptr;
const unsigned char* public_key_data = public_key.data();
ec_group = d2i_ECPKParameters(nullptr, &public_key_data, public_key.length());
if (ec_group == nullptr) {
return false; // RETURN POINT
}
EC_KEY* ec_key = EC_KEY_new();
if (ec_key == nullptr) {
EC_GROUP_free(ec_group);
return false;
}
if (!EC_KEY_set_group(ec_key, ec_group)) {
EC_GROUP_free(ec_group);
EC_KEY_free(ec_key);
return false;
}
bool is_signature_valid =
ECDSA_verify(0, hash.data(), hash.size(), signature.data(),
signature.length(), ec_key);
EC_GROUP_free(ec_group);
EC_KEY_free(ec_key);
return is_signature_valid;
}
UPDATE: 其他進口試試(但是仍然無法正常工作):
const unsigned char* public_key_data = public_key.data();
EC_KEY* ec_key =
o2i_ECPublicKey(nullptr, &public_key_data, public_key.length());
if (ec_key == nullptr) {
return false; // RETURN POINT
}
bool is_signature_valid =
ECDSA_verify(0, hash.data(), hash.size(), signature.data(),
signature.length(), ec_key);
EC_KEY_free(ec_key);
出口:
function ecdsa_export_pub_key(key) {
return window.crypto.subtle.exportKey(
"spki",
key);
}
更新2:
我生成的PEM密鑰(從JS導出的密鑰),但是伯,我不使用PEM密鑰。在JavaScript中導出公鑰之後,我從ArrayBuffer創建一個新的Uint8Array,通過WebSocket(二進制框架)將其發送到服務器,並嘗試解析它。收到的uint8_t數組總是158字節長度。我使用P-521 - secp521r1。
輸出的私鑰在pkcs8!
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIApK1m/qpIAZ1iENht
XJxng4bdur6YV2SpMs+uFtSiJ/n96HbjVkqSENavv7vblIow+i5QUhaOkqSNWi0B
7x695C6hgYkDgYYABAATsbs5B+ebSwoIXD6RD2NYONzSWOtt0SigPM27pdYEWpld
/6j6S34gvRHQwDSMzs6//1zVE20Mn+izNM0KPWhRewD6SotR8/2QGWB5uo8GiXx1
RLyBp+TOurQLEsYwiWSLkUIUMvPH/6WCxSNO4FzBf617PRqs7Zv3Vo98d9JH/3mI
TA==
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAE7G7OQfnm0sKCFw+kQ9jWDjc0ljr
bdEooDzNu6XWBFqZXf+o+kt+IL0R0MA0jM7Ov/9c1RNtDJ/oszTNCj1oUXsA+kqL
UfP9kBlgebqPBol8dUS8gafkzrq0CxLGMIlki5FCFDLzx/+lgsUjTuBcwX+tez0a
rO2b91aPfHfSR/95iEw=
-----END PUBLIC KEY-----
一些細節:
% openssl asn1parse -inform PEM -in pub.pem
0:d=0 hl=3 l= 155 cons: SEQUENCE
3:d=1 hl=2 l= 16 cons: SEQUENCE
5:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
14:d=2 hl=2 l= 5 prim: OBJECT :secp521r1
21:d=1 hl=3 l= 134 prim: BIT STRING
% openssl asn1parse -inform PEM -in priv.pem
0:d=0 hl=3 l= 238 cons: SEQUENCE
3:d=1 hl=2 l= 1 prim: INTEGER :00
6:d=1 hl=2 l= 16 cons: SEQUENCE
8:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
17:d=2 hl=2 l= 5 prim: OBJECT :secp521r1
24:d=1 hl=3 l= 214 prim: OCTET STRING [HEX DUMP]:3081D3020101044200A4AD66FEAA48019D6210D86D5C9C678386DDBABE985764A932CFAE16D4A227F9FDE876E3564A9210D6AFBFBBDB948A30FA2E5052168E92A48D5A2D01EF1EBDE42EA1818903818600040013B1BB3907E79B4B0A085C3E910F635838DCD258EB6DD128A03CCDBBA5D6045A995DFFA8FA4B7E20BD11D0C0348CCECEBFFF5CD5136D0C9FE8B334CD0A3D68517B00FA4A8B51F3FD90196079BA8F06897C7544BC81A7E4CEBAB40B12C63089648B91421432F3C7FFA582C5234EE05CC17FAD7B3D1AACED9BF7568F7C77D247FF79884C
錯誤代碼時呼叫o2i_ECPublicKey:
(呼叫具有相同的數據,但錯誤是每次都不同 - 這是無論如何重複。)
error:10067066:elliptic curve routines:ec_GFp_simple_oct2point:invalid
error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib
error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
error:10067066:elliptic curve routines:ec_GFp_simple_oct2point:invalid
error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib
更新3:
從C++,我寫出所接收的數據(密鑰)到一個文件:
% % openssl asn1parse -inform DER -in data.bin
0:d=0 hl=3 l= 155 cons: SEQUENCE
3:d=1 hl=2 l= 16 cons: SEQUENCE
5:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
14:d=2 hl=2 l= 5 prim: OBJECT :secp521r1
21:d=1 hl=3 l= 134 prim: BIT STRING
%
% hexdump data.bin
0000000 8130 309b 0610 2a07 4886 3dce 0102 0506
0000010 812b 0004 0323 8681 0400 1300 bbb1 0739
0000020 9be7 0a4b 5c08 913e 630f 3858 d2dc eb58
0000030 d16d a028 cd3c a5bb 04d6 995a ff5d faa8
0000040 7e4b bd20 d011 34c0 ce8c bfce 5cff 13d5
0000050 0c6d e89f 34b3 0acd 683d 7b51 fa00 8b4a
0000060 f351 90fd 6019 ba79 068f 7c89 4475 81bc
0000070 e4a7 bace 0bb4 c612 8930 8b64 4291 3214
0000080 c7f3 a5ff c582 4e23 5ce0 7fc1 7bad 1a3d
0000090 edac f79b 8f56 777c 47d2 79ff 4c88
000009
十六進制編碼的出口SPKI(該WebCrypto的結果出口):
Private:
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIApK1m/qpIAZ1iENhtXJxng4bdur6YV2SpMs+uFtSiJ/n96HbjVkqSENavv7vblIow+i5QUhaOkqSNWi0B7x695C6hgYkDgYYABAATsbs5B+ebSwoIXD6RD2NYONzSWOtt0SigPM27pdYEWpld/6j6S34gvRHQwDSMzs6//1zVE20Mn+izNM0KPWhRewD6SotR8/2QGWB5uo8GiXx1RLyBp+TOurQLEsYwiWSLkUIUMvPH/6WCxSNO4FzBf617PRqs7Zv3Vo98d9JH/3mITA==
公開:
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAE7G7OQfnm0sKCFw+kQ9jWDjc0ljrbdEooDzNu6XWBFqZXf+o+kt+IL0R0MA0jM7Ov/9c1RNtDJ/oszTNCj1oUXsA+kqLUfP9kBlgebqPBol8dUS8gafkzrq0CxLGMIlki5FCFDLzx/+lgsUjTuBcwX+tez0arO2b91aPfHfSR/95iEw=
更新4:
私鑰JWK格式:
{
"crv":"P-521",
"d":"AKStZv6qSAGdYhDYbVycZ4OG3bq-mFdkqTLPrhbUoif5_eh241ZKkhDWr7-725SKMPouUFIWjpKkjVotAe8eveQu",
"ext":true,
"key_ops":["sign"],
"kty":"EC",
"x":"ABOxuzkH55tLCghcPpEPY1g43NJY623RKKA8zbul1gRamV3_qPpLfiC9EdDANIzOzr__XNUTbQyf6LM0zQo9aFF7",
"y":"APpKi1Hz_ZAZYHm6jwaJfHVEvIGn5M66tAsSxjCJZIuRQhQy88f_pYLFI07gXMF_rXs9Gqztm_dWj3x30kf_eYhM"
}
請創建一個測試密鑰,然後以某種編碼(hex,base64,pem)將其發佈,以便我們可以對其進行破解。 – jww
@jww我加了他們。 – bsz
您添加了pem編碼密鑰,但它們是您遇到問題的密鑰(聽起來像答案爲否)?如果沒有,那麼他們的演示文稿格式是什麼?如果它的ASN/1的DER,然後只是十六進制編碼併發布它們。我們總是可以剝離我們不需要的東西(比如十六進制編碼)。但是我們不能創造我們沒有的鑰匙。 – jww