我正在創建一個程式,給定一個純十六進制格式的證書,將提取并驗證數字簽名。
我有以下十六進制格式的示例證書:
308206cd308205b5a003020102021001c3f8388b669f492cfac8731937fc8e300d06092a864886f70d01010b0500304f310b300906035504061302555331153013060355040a130c446967694365727420496e633129302706035504031320446967694365727420544c532052534120534841323536203230323020434131301e170d3232303132313030303030305a170d3233303230353233353935395a3079310b3009060355040613025553311330110603550408130a43616c69666f726e6961310f300d06035504071306497276696e6531253023060355040a131c426c697a7a61726420456e7465727461696e6d656e742c20496e632e311d301b0603550403131475732e61637475616c2e626174746c652e6e657430820122300d06092a864886f70d01010105000382010f003082010a0282010100b3838051fd24a13681e97e557476f22891b05355157c9ded1c7ca610f07f4d5a5c987e88318c213a62481fc0fd43ece409170cef6ac95ab106dd4cd046e4c3660097d2aeefffc7fe470307b17c9febd3799352a1971b0303360bd9c028c1939d9fbd0148eb0d4dbebfad23e5e3ab3b94943351cd8fe11556bf1ec7370a615ed74c5f5d66d62799f66bb1d1f3a4b661173cafed4b722b03f046572e73eae216b8e35e73add6cb86243fe4b457ffb8e6baf50af563110da121255c676248e8976ab1fe8c221a964cc550901b5191730aa6d616dc6aa9ee87fcaf7ac56e48f1592eeeb836065dd6c1078e724db7607677298169d9225eac5fdc974a21565621d4fb0203010001a382037930820375301f0603551d23041830168014b76ba2eaa8aa848c79eab4da0f98b2c59576b9f4301d0603551d0e04160414402287da2dd56eddfa85ccda1f946e493a08a99b301f0603551d1104183016821475732e61637475616c2e626174746c652e6e6574300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230818f0603551d1f0481873081843040a03ea03c863a687474703a2f2f63726c332e64696769636572742e636f6d2f4469676943657274544c53525341534841323536323032304341312d342e63726c3040a03ea03c863a687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274544c53525341534841323536323032304341312d342e63726c303e0603551d20043730353033060667810c0102023029302706082b06010505070201161b687474703a2f2f7777772e64696769636572742e636f6d2f435053307f06082b0601050507010104733071302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304906082b06010505073002863d687474703a2f2f636163657274732e64696769636572742e636f6d2f4469676943657274544c53525341534841323536323032304341312d312e637274300c0603551d130101ff0402300030820180060a2b06010401d679020402048201700482016c016a007700e83ed0da3ef5063532e75728bc896bc903d3cbd1116beceb69e1777d6d06bd6e0000017e7eaf5af30000040300483046022100ce2d33ce8de3764ccc9d8ac03b936612fd10a4fc1815b3e092352643aa8d07e9022100e2a741a4c3ef5c90882f66951075be12ad54bdc573bd3ae3b17c662f63c6e29400760035cf191bbfb16c57bf0fad4c6d42cbbbb627202651ea3fe12aefa803c33bd64c0000017e7eaf5b14000004030047304502201ef42884353339d4921bf2e47af540b15af6bab94de74c3e3a1224418e9bc4ef0221008846deaa381d08b65607dc3290ba152f1c5aab5c7d03cf116682da8a45922f18007700b3737707e18450f86386d605a9dc11094a792db1670c0b87dcf0030e7936a59a0000017e7eaf5b4400000403004830460221008dc3b79af62dce53af04b8959afcb1f858bea16872eba97b5cc2c8f308b32d490221009b658042c5a0841d670ac1303c06b42e6a494596cb5e333fbdeddc9248e05dcd300d06092a864886f70d01010b0500038201010010170d137389daa010c477c0dde1af6529725489ad07822ace988cb78969683e1686a9fcde2d166b2c7ae5774e782ce7270904fb5abfdc0de25123d7cbcbd855598d35a027d1f5bdf3bd754eb3c6c9b7cc74de740b0b576c629dfd9ff5cca4d773f8bb499cc6f0aa39f269d219f019e62cbb354f32fa171226f58a4582b711e779268baa5d4bcc44f9dda3f2b867344ea29ecb6e28f4f818ef3594da16dc882cfd65cd2875a50d9ee9dff5d297135b5890ce4f583ab770c1d79bd5e7c4b2e1ae2ca0425cf63e12f151e8b6c6228ee53be299ee5ef09c85df0ad24b66e32b37f93193c2495f2de78d28126b3aa8a406b44d8469292fc242c5f39db44be56f4d91
從這里,我能夠成功地匯出數字簽名(位于上面 cert hex 的末尾)
10170d137389daa010c477c0dde1af6529725489ad07822ace988cb78969683e1686a9fcde2d166b2c7ae5774e782ce7270904fb5abfdc0de25123d7cbcbd855598d35a027d1f5bdf3bd754eb3c6c9b7cc74de740b0b576c629dfd9ff5cca4d773f8bb499cc6f0aa39f269d219f019e62cbb354f32fa171226f58a4582b711e779268baa5d4bcc44f9dda3f2b867344ea29ecb6e28f4f818ef3594da16dc882cfd65cd2875a50d9ee9dff5d297135b5890ce4f583ab770c1d79bd5e7c4b2e1ae2ca0425cf63e12f151e8b6c6228ee53be299ee5ef09c85df0ad24b66e32b37f93193c2495f2de78d28126b3aa8a406b44d8469292fc242c5f39db44be56f4d91
然后,我獲取頒發此證書的公鑰,并使用它來解密數字簽名摘要,如下所示:
3031300d0609608648016503040201050004200bf3dcf2340b972e97fe3c8493e11eeee01f298939734690d0b4e79e1f5701b4
此時我試圖通過創建整個 SSL 證書的哈希來驗證數字簽名(此證書使用 SHA256 哈希作為摘要):
hash('sha256', hex2bin($CertWithoutSignature))
其中 $CertWithoutSignature 與上面的十六進制相同(上面的第一個十六進制字串)沒有數字簽名(上面的第二個十六進制字串)。
此時我有點困惑,因為不僅sha256哈希的長度不匹配,資料也不匹配。我知道我正在正確解密摘要,否則如果密鑰無效等,我會收到錯誤訊息。但是提取的值是 102 個字符長,并且與我從 sha256 得到的值不匹配,因為字串的長度完全不同。基本上我知道如果我能讓它們匹配是有效的,因為這意味著檔案是完全相同的,因此會得到相同的哈希值。任何幫助表示贊賞。謝謝。
uj5u.com熱心網友回復:
假設您在證書中使用 PKCS#1 v1.5 填充,您忘記了對哈希進行編碼然后在簽名中填充。
將所有內容散列到簽名也不正確,您需要散列 TBSCertificate,其中 TBS 表示待簽名。
有關更多資訊,我強烈建議閱讀 RFC 5280 中的 X.509 規范。而且,由于 ASN.1 編碼器/解碼器相當復雜,您可能希望使用庫函式而不是自己編程。
uj5u.com熱心網友回復:
您將需要使用實際的 SSL 庫來正確驗證簽名,而不僅僅是比較幾個哈希值。您至少還需要簽名證書。
為了讓您開始,您需要將該證書轉換為 PEM 格式,以便 OpenSSL 喜歡它。
// hex-encoded binary format
$cert_hex = '308206cd...';
// convert to PEM format
$cert_pem = sprintf(
"-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n",
implode("\n", str_split(base64_encode(hex2bin($cert_hex)), 64))
);
// read in as an OpenSSL resource
$cert = openssl_x509_read($cert_pem);
// check the fingerprint just to verify it loaded
$fp = openssl_x509_fingerprint($cert, 'sha256');
var_dump($fp);
輸出:
string(64) "d74157547fb287694b95b2533588c71f8706b0960e023fc4317f4f9a49ad2721"
在此之后,您可能希望以相同的方式加載簽名證書并將它們都輸入openssl_x509_verify(),例如:
openssl_x509_verify($cert, $signing_cert);
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/482784.html
