0

嗨,我正在构建 REST 服务并计划消除从该项目(目前使用 PHP 编写的 REST 服务器)开发客户端和服务器的语言限制。

为了安全起见,我正在验证他们的哈希码以及他们的客户端应用程序签名。目前哈希是成功的,但对于签名它总是失败。

每个客户端都有自己的私钥,在服务器上我们将有他们的公钥来验证签名,每个对服务器的请求都会发送一个签名。如果客户端是 Web 服务器,则所有用户只有一个私钥。如果客户端是本机应用程序 (C#),则每个已安装的客户端应用程序都将拥有其唯一的私钥。

PHP 客户端到 PHP REST 服务器 -> 计算哈希正常,验证客户端签名正常 C# 客户端 (winapp) 到 PHP REST 服务器 -> 计算哈希正常,验证客户端签名失败

将来我想尝试使用 JAVA,反之亦然。

我使用简单的方法来创建自签名证书

openssl genrsa -des3 -out netclient.key 2048
openssl req -new -x509 -key netclient.key -out netclient.crt
openssl pkcs12 -export -inkey netclient.key -in netclient.crt -out netclient.p12

这是我使用 C# 对数据进行签名的代码

public static string (string Base64EncryptedData ) {
X509Certificate2 my;
my = new X509Certificate2("cert/netclient.p12", "abcdefg", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

RSACryptoServiceProvider csp = null;

csp = (RSACryptoServiceProvider)my.PrivateKey;

SHA1Managed sha1 = new SHA1Managed();
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(Base64EncryptedData);
byte[] hash = sha1.ComputeHash(data);

return Convert.ToBase64String(csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"))); 
}

它返回一个签名(base64),我使用 GET 方法将其发送到 PHP REST 服务器。在 PHP 服务器上,我重新计算哈希并验证,但它从不返回 1。目前我手动将所有密钥复制到服务器。

set_include_path(get_include_path() . PATH_SEPARATOR ."lib");
include("Crypt/RSA.php");

$p12cert = array();
$fp=fopen("cert/netclient.p12","r");
$priv_key=fread($fp,8192);
fclose($fp);
openssl_pkcs12_read($priv_key, $p12cert, "abcdefg");

//try using the phpseclib library from http://phpseclib.sourceforge.net
//req() will get all the $_POST, $_GET data req("signature") = $_GET["signature"];
//$hash_request is an base64_encode string same exact value as the one in C#
$rsa = new Crypt_RSA();
$rsa->setHash("sha1");
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->loadKey($p12cert["cert"]);
$verified_phpseclib = $rsa->verify($hash_request, base64_decode(req("signature"))) ? "verified" : "diff";

//try using php built in openssl 
$verified_builtin = openssl_verify($hash_request, base64_decode(req('signature')), $p12cert["cert");

非结果返回“已验证”或“1”

可能是因为当 C# 对数据进行签名时,数据的格式是 byte[] 吗?还是有其他原因?

我在 linux php 中运行所有代码 - 使用 apache2 c# - 使用 monodevelop


这是我使用 openssl_pkcs12_read 阅读后的 pk12 数组,您可以在此处下载

Array
(
    [cert] => -----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANjuyBraeAN0MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTMwMzE5MDA0ODI0WhcNMTMwNDE4MDA0ODI0WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAojE1Md/DET9mvKpoNJvb+mbGdTfSYuXQurGxb5pU0ba+gVeARbc8fjaK
D/2EKhUP/7240a31e5qI/2UlgiHO+ghQKDPo+5W5CetDVR1oMbWVA1fp7/gv8DEV
AvNV9nVkYzxnoVPs+W0MhMlWPrhCNSqQ28BbbL0EzXwXESnMw0I2VAhGWDNG0zSl
U03l5zh8jzzRKKK+gw4gIKo0u4lEUqB52MaXPzdwQkOEXRUdT+l1vK3DGfQycMrm
gZEN6IXDvpSFcQfHJlICK06+JNgDM0tYbif2mMfDEPKeFIjGC8S2ZDTZlR92LCk1
/WUGhdDFobbLAOx40M/etOcaEN1bgQIDAQABo1AwTjAdBgNVHQ4EFgQUTr0r49JA
DUKKiIQkRVlog4T952AwHwYDVR0jBBgwFoAUTr0r49JADUKKiIQkRVlog4T952Aw
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAO2IwjeIEVy8aLCOTjCkt
fTyLYuoiex+Xa/Dy2Xdl51Q44uAjCeSVsm1mXko+cZSypngGDu8W97sifzeR+pmW
7r6r+Rj+5pZcQiLQOCUQrXVpqHeiCS8QpOhpxGF+TOLy1O9zcqQwEiohKmzJB++d
1NM8//OBx1/Nyu7eLTKrTqfBdhuXfee963HVF9uBxwV8oa3UTQfhKu2vwJ64pcbU
5OVQw4rfhfSYhB1uu+zMQhCZ3hsroj2rC6Kfb8t3BNzngQwiqDBprmJznmJY38pW
kw0NIx+GrO1NUu+Ydl/7MXChujQajqSkG65Z9iJ8G7eegrY988INPVIfitIopWF+
jg==
-----END CERTIFICATE-----

    [pkey] => -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCiMTUx38MRP2a8
qmg0m9v6ZsZ1N9Ji5dC6sbFvmlTRtr6BV4BFtzx+NooP/YQqFQ//vbjRrfV7moj/
ZSWCIc76CFAoM+j7lbkJ60NVHWgxtZUDV+nv+C/wMRUC81X2dWRjPGehU+z5bQyE
yVY+uEI1KpDbwFtsvQTNfBcRKczDQjZUCEZYM0bTNKVTTeXnOHyPPNEoor6DDiAg
qjS7iURSoHnYxpc/N3BCQ4RdFR1P6XW8rcMZ9DJwyuaBkQ3ohcO+lIVxB8cmUgIr
Tr4k2AMzS1huJ/aYx8MQ8p4UiMYLxLZkNNmVH3YsKTX9ZQaF0MWhtssA7HjQz960
5xoQ3VuBAgMBAAECggEAB/TgBi1S9XKlyJWXfRU0SmlmTPPLF1zsy2vSJ4ZrqMoN
OG0hdsoRZqOoTDaEmEfmPAaDnY2qIEEpfVXp7CNacvubaw143Xav2CO5buB9bwrY
X4ydhk8nkuHlhPqI+gkyPogFEW37jxTha1YxK+yAGvmWl6EtGv1+0dHHk+j4CZAO
9DH1gZRBOXyeAJAhYuBMxxKfZhBNgGHzLtf9SGoOd2v9ya/h4CuqYh/CoxHGM/w1
uE6M2CKxSuZtqdtiJnoYcmAnDLACDmVHQNbFMEyC3ALrixgTj1p9aYPi8P/9BVKv
+T6cCmRQIl4VY4Ir0PCbai6BQaP6TIbAo0lt9cefUQKBgQDV2KKuc/TsZgrl+ijV
vW1kf46X1Squ8AqPgJnXYM5M4kG+17AecV25sm1oHmzN0ChwvWYotfhLMSqdH+1l
5zMYMwjTle9BkQXELyAvKiKND5I42DtTE04YnHi7HDlaJmOCa3WTTPjJiyIZC+9S
Lpc3gDwP8VSBcq2V2t/SMw9+nQKBgQDCKfIUJWW0WHkESmc8rJDBUWueUVfEWh/d
9ZG/gIapSXnJcTp/fRDZsaqS0pI7c8bvdPJPkQKO0M7Sy2E/OjyKOT5X4+4FguCd
XlwaUhVRycMxGjb1Q4pTlPCnQkoBVKQ5oW4IVQW/ILtT6wuJQPmqkwiXN6CSHzmF
w1RW+pUpNQKBgDXEeHLgmO5vYcIdOfMz47NnFxU59bdyh1U5gnTS1Ewkf19an9+n
pWcxY6zQKY8+DUz7cho+VqWhQROsmWYL0Z7+BfQdOMEFk6uWJcN2FqXdCmjchV4H
9pTdksWI/SqbiF2cYz2cFtml7/bYN140dLTxuyhPB25cxSRumeQiDn1JAoGBAJDf
w2UM0mpSaVmuOoGnMQtNuUMT5qz3ojd3eByvxcqirGCGP+PIab5FNsT+oWYC6Tja
xcJgrMvrOadHYXRP+8QXGlFyHLO4B+jj800gWhAAv8fvi3pNvvTGeRoT+Cwt/6uQ
rA1Dg1otDhl7k8wB00hXFV3ff8wHyF/qcw/DQXDRAoGBAJGvJSl9yIr5v3ooZ6BV
FtDcDTPFGxQCyqvfi5RzKW65Wqu1ZL7jSiOPcY4+418Zifnfyfr/9IZjl9EKPjhC
/fNqptnuA7DKPDKkQIeQSwtHF9HGVoqG0JGOmYCeCZxQK6eZhiuU8VohAAbzsdu8
PgxyS/PRbCsXP4p+OjR1i+3C
-----END PRIVATE KEY-----
)
4

1 回答 1

1

试试这个:

<?php
set_include_path(get_include_path() . PATH_SEPARATOR ."lib");
include('File/X509.php');

$p12cert = array();
$fp=fopen("cert/netclient.p12","r");
$priv_key=fread($fp,8192);
fclose($fp);
openssl_pkcs12_read($priv_key, $p12cert, "abcdefg");

$x509 = new File_X509();
$x509->loadX509($p12cert["cert"]);
$pubkey = $x509->getPublicKey();
$pubkey->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$verified_phpseclib = $pubkey->verify($hash_request, base64_decode(req("signature"))) ? "verified" : "diff";
于 2013-03-20T05:10:22.960 回答