{"action":"closed","issue":{"url":"https://api.github.com/repos/guanzhi/GmSSL/issues/449","repository_url":"https://api.github.com/repos/guanzhi/GmSSL","labels_url":"https://api.github.com/repos/guanzhi/GmSSL/issues/449/labels{/name}","comments_url":"https://api.github.com/repos/guanzhi/GmSSL/issues/449/comments","events_url":"https://api.github.com/repos/guanzhi/GmSSL/issues/449/events","html_url":"https://github.com/guanzhi/GmSSL/issues/449","id":302957314,"number":449,"title":"GmSSL SM2签名验签与UKey, 加密机的兼容性问题","user":{"login":"kevinhe79","id":37100847,"avatar_url":"https://avatars0.githubusercontent.com/u/37100847?v=4","gravatar_id":"","url":"https://api.github.com/users/kevinhe79","html_url":"https://github.com/kevinhe79","followers_url":"https://api.github.com/users/kevinhe79/followers","following_url":"https://api.github.com/users/kevinhe79/following{/other_user}","gists_url":"https://api.github.com/users/kevinhe79/gists{/gist_id}","starred_url":"https://api.github.com/users/kevinhe79/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kevinhe79/subscriptions","organizations_url":"https://api.github.com/users/kevinhe79/orgs","repos_url":"https://api.github.com/users/kevinhe79/repos","events_url":"https://api.github.com/users/kevinhe79/events{/privacy}","received_events_url":"https://api.github.com/users/kevinhe79/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-03-07T04:03:01Z","updated_at":"2018-03-09T05:52:39Z","closed_at":"2018-03-09T05:52:39Z","author_association":"NONE","body":"关老师：\r\n  您好！\r\n\r\n  工作中有通过UKey签名验签及通过密码服务器签名验签的需求。想转用GmSSL实现软件算法，但测试中发现用UKEY或密码机签出的内容不能用GmSSL验证（UKEY和密码机是能相互验证的)，相反也一样。\r\n\r\n  在Issues中查找到有人反应过这个问题，您也做过回应，参见下面Issue号： \r\n============================================\r\n  gmssl 无法验签ukey中sm2算法生成的签名 \r\n  #369 by RubicPhil was closed on Nov 11 2017 \r\n===========================================\r\n\r\n我参考关老师您的建议将X, Y封装为EVP_PKEY结构直接调用，也已保存为PEM做过命令行测试， GmSSL一样不能验证通过。\r\n======================================================\r\ngmssl pkeyutl -verify -pubin -inkey D:\\Work\\svn\\PkiDemoProject\\OpenSSL\\Debug\\publicKey.pem -pkeyopt ec_scheme:sm2 -in D:\\Work\\svn\\PkiDemoProject\\OpenSSL\\Debug\\unsignedData.bin -sigfile D:\\Work\\svn\\PkiDemoProject\\OpenSSL\\Debug\\signedData.bin\r\nSignature Verification Failure\r\n\r\n测试代码如下：\r\n===============================================================\r\nbool SM2Verify2(const char* signCert, bool isPem, const unsigned char* toBeSignedData, const unsigned int toBeSignedLen, unsigned char* signedData, unsigned int signedDataLen)\r\n{\r\n\tbool ret = false;\r\n\t//char key[65] = \"\\x6d\\x63\\x5e\\x4f\\x2d\\x62\\xd3\\x61\\xe3\\xa5\\x07\\xa2\\x5e\\x7a\\xae\\x12\\xbe\\xf1\\x97\\x40\\xe7\\x5d\\xaf\\x82\\x4d\\xec\\x28\\xb7\\x39\\x9c\\xe5\\x5f\\x12\\x88\\x61\\xa8\\x3e\\xaf\\xa6\\xf5\\x08\\xcf\\xfe\\xc4\\x43\\x25\\xf1\\x0b\\x22\\x81\\x47\\x84\\x75\\xa7\\x27\\x7b\\x5e\\xcf\\x3a\\x01\\xce\\xfa\\x8e\\x6f\";\r\n\tchar keyXStr[65] = \"6d635e4f2d62d361e3a507a25e7aae12bef19740e75daf824dec28b7399ce55f\";\r\n\tchar keyYStr[65] = \"128861a83eafa6f508cffec44325f10b2281478475a7277b5ecf3a01cefa8e6f\";\r\n\tBIGNUM *X = NULL, *Y = NULL;\r\n\t//BIO *bio = NULL;\r\n\tEC_KEY\t*ecKey = NULL;\r\n\tEVP_PKEY *evpKey = NULL;\r\n\tEC_GROUP *group = NULL;\r\n\r\n\tgroup = EC_GROUP_new_by_curve_name(NID_sm2p256v1);\r\n\tif(!group)\r\n\t{\r\n\t\tprintf(\"EC_GROUP_new_by_curve_name err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\tecKey = EC_KEY_new();\r\n\t/* 设置密钥参数 */\r\n\tif (!ecKey || EC_KEY_set_group(ecKey, group) != 1)\r\n\t{\r\n\t\tprintf(\"EC_KEY_set_group err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\tBN_hex2bn(&X, keyXStr);\r\n\tBN_hex2bn(&Y, keyYStr);\r\n\tif(1 != EC_KEY_set_public_key_affine_coordinates(ecKey, X, Y))\r\n\t{\r\n\t\tprintf(\"EC_KEY_set_public_key err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\r\n\t/*\r\n\tbio = BIO_new_file(\"public.pem\", \"wb\");\r\n\tif (!bio)\r\n\t{\r\n\t\tprintf(\"fopen err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tif(1 != PEM_write_bio_EC_PUBKEY(bio, ecKey))\r\n\t{\r\n\t\tprintf(\"fopen err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\r\n\r\n\tBIO_free_all(bio);\r\n\tbio = NULL;\r\n\t*/\r\n\r\n\tevpKey = EVP_PKEY_new();\r\n\tif (!evpKey || 1 != EVP_PKEY_set1_EC_KEY(evpKey, ecKey))\r\n\t{\r\n\t\tprintf(\"EVP_PKEY_new or EVP_PKEY_set1_EC_KEY err.\\n\");\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tret = SM2VerifyByKey(evpKey, toBeSignedData, toBeSignedLen, signedData, signedDataLen);\r\n\r\nend:\r\n\tif (X)\r\n\t\tBN_free(X);\r\n\tif (Y)\r\n\t\tBN_free(Y);\r\n\tif (group)\r\n\t\tEC_GROUP_free(group);\r\n\tif (ecKey)\r\n\t\tEC_KEY_free(ecKey);\r\n\tif (evpKey)\r\n\t\tEVP_PKEY_free(evpKey);\r\n\t/*\r\n\tif (bio)\r\n\t\tBIO_free_all(bio);\r\n\t*/\r\n\r\n\treturn ret;\r\n}\r\n\r\nSM2VerifyByKey的实现代码如下：\r\n================================================================\r\nbool SM2VerifyByKey(EVP_PKEY *pkey, const unsigned char* toBeSignedData, const unsigned int toBeSignedLen, unsigned char* signedData, unsigned int signedDataLen)\r\n{\r\n\tbool ret = false;\r\n\r\n\tEVP_MD_CTX *mdctx = NULL;\r\n\r\n\t/* verify the sign */\r\n\tmdctx = EVP_MD_CTX_create();\r\n\tif (!(mdctx)) {\r\n\t\tfprintf(stderr, \"error: %s %d\\n\", __FILE__, __LINE__);\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tconst EVP_MD *md = EVP_sm3();\r\n\tif (!EVP_VerifyInit_ex(mdctx, md, NULL)) {\r\n\t\tfprintf(stderr, \"error: %s %d\\n\", __FILE__, __LINE__);\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tif (!EVP_VerifyUpdate(mdctx, toBeSignedData, toBeSignedLen)) {\r\n\t\tfprintf(stderr, \"error: %s %d\\n\", __FILE__, __LINE__);\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tint i = EVP_VerifyFinal(mdctx, signedData, signedDataLen, pkey);\r\n\tif (i != 1) {\r\n\t\tfprintf(stderr, \"EVP_VerifyFinal return %d, error: %s %d\\n\", i, __FILE__, __LINE__);\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tret = true;\r\n\r\nend:\r\n\tif (mdctx)\r\n\t\tEVP_MD_CTX_free(mdctx);\r\n\r\n\treturn ret;\r\n}\r\n\r\n\r\n我还尝试过SM2 demo中的模式，问题一样\r\n=============================================\r\nbool SM2Verify(const char* signCert, bool isPem, const unsigned char* toBeSignedData, const unsigned int toBeSignedLen, unsigned char* signedData, unsigned int signedDataLen)\r\n{\r\n\tsm3_ctx_t sm3;\r\n\tsm3_init(&sm3);\r\n\tsm3_update(&sm3, toBeSignedData, toBeSignedLen);\r\n\tunsigned char digest[SM3_DIGEST_LENGTH];\r\n\tsm3_final(&sm3, digest);\r\n\r\n\tbool ret = false;\r\n\tEVP_PKEY *pkey = NULL;\r\n\tEVP_MD_CTX *mdctx = NULL;\r\n\r\n\t/* get the pub key from the cert*/\r\n\tX509 *cert = NULL;\r\n\tif (isPem)\r\n\t\tcert = fileio_read_pem_cert(signCert);\r\n\telse\r\n\t\tcert = fileio_read_der_cert(signCert);\r\n\tif (!cert)\r\n\t\tgoto end;\r\n\tpkey = X509_get_pubkey(cert);\r\n\tif (pkey == NULL) {\r\n\t\tfprintf(stderr, \"error: %s %d\\n\", __FILE__, __LINE__);\r\n\t\tgoto end;\r\n\t}\r\n\r\n\tint vRet = SM2_verify(0, digest, SM3_DIGEST_LENGTH, signedData, signedDataLen, pkey->pkey.ec);\r\n\tprintf(\"SM2_verify return %d.\\n\", vRet);\r\n\tif (1 == vRet)\r\n\t{\r\n\t\tret = true;\r\n\t}\r\n\telse {\r\n\t\tprintf_error();\r\n\t}\r\n\r\nend:\r\n\tif (cert)\r\n\t\tX509_free(cert);\r\n\tif (pkey)\r\n\t\tEVP_PKEY_free(pkey);\r\n\r\n\treturn ret;\r\n}\r\n\r\n我附上了测试数据和公钥\r\n请关老师指出我代码的问题，谢谢！\r\n\r\n\r\n\r\n\r\n[Debug.zip](https://github.com/guanzhi/GmSSL/files/1787721/Debug.zip)\r\n\r\n\r\n\r\n\r\n\r\n"}}
{"actor":{"display_login":"kevinhe79"}}