Closed nirvana72 closed 4 months ago
我指的是 就是明文密钥的base64, 你这个是asn1过的base64, 就是文件密钥里的那种,可以解开,或者用文件密钥的方式处理
我用另一个issues 中您提到的方法, 用外部文件方式base64转hex
-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEUwulPOFFcaAevSmMgWHV/wPdV6HfXxwEgTzrel6o7o9FTo+6Y5NCi0EY8p4aQ+P3qaoghrBy0VLYC/RDpOIRRQ== -----END PUBLIC KEY-----
`$publickeyFile = "sm2pri.pem";
$adapter = RtEccFactory::getAdapter();
$sigSerializer = new DerSignatureSerializer();
$keyData = file_get_contents( $publickeyFile );
$derSerializer = new DerPublicKeySerializer( $adapter );
$pemSerializer = new PemPublicKeySerializer( $derSerializer );
$key = $pemSerializer->parse( $keyData );
$pubKeyX = $this->decHex( $key->getPoint()->getX() );
$pubKeyY = $this->decHex( $key->getPoint()->getY() );
$publickey = $pubKeyX.$pubKeyY;`
转出的公钥可以使用并加密成功
但我以同样的方式转私钥的时候, 却不成功
-----BEGIN EC PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXpjk0KLQRjynhpD4/epqiCGsHLRUtgL9EOk4hFF== -----END EC PRIVATE KEY-----
/vendor/mdanter/ecc/src/Serializer/PublicKey/Der/Parser.php - line:51 报错 Invalid data.
私钥与公钥的格式是不一样的, 不能用一样的代码解,可用 asn1组件单独解开
代码库中, /test/data/sm2.pem 私钥长度是 164 位, 我用
\Rtgm\util\MyAsn1::decode_file($privatekeyFile);
或
$adapter = RtEccFactory::getAdapter();
$privatekeyFile = "sm2pri.pem";
$pemSerializer = new PemPrivateKeySerializer(new DerPrivateKeySerializer($adapter));
$keyData = file_get_contents($privatekeyFile);
$key = $pemSerializer->parse($keyData);
都可以解出结果, 虽然目前还不知道哪个是16位私钥
但是我的java对接方给我提供的base64位私钥是
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgFtsitF4zKnGftxjR6U9HqVVEPk24N+o3rLD+jhYFnr2gCgYIxxxBgi2hRANCAARTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxSBPOt6Xqjuj0VOj7pjk0KLQRjynhpD4/epqiCGsHLRUtgL9EOk4hFF==
用这个就解不出来
比对了一下, 我的对接方给的私钥是 202位的, 好像记得base64编码长度都是3的倍数,
是对方给错字符串了, 还是我的方法不对
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgFtsitF4zKnGftxjR6U9HqVVEPk24N+o3rLD+jhYFnr2gCgYIKoEcz1UBgi2hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyBYdX/A91Xod9fHASBPOt6Xqjuj0VOj7pjk0KLQRjynhpD4/epqiCGsHLRUtgL9EOk4hFF==
上面这个 202位长度的私钥, 用
\Rtgm\util\MyAsn1::decode_file($privatekeyFile);
解出来是
array(3) { [0] => string(2) "00" [1] => array(2) { [0] => string(11) "ecPublicKey" [1] => string(3) "sm2" } [2] => string(242) "3077020101042016DB22B45E332A719FB718D1E94F47A955443E4DB837EA37ACB0FE8E16059EBDA00A06082A811CCFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxA01EBD298C8161D5FF03DD57A1DF5F1C04813CEB7A5EA8EE8F454E8FBA6393428B4118F29E1A43E3F7A9AA2086B072D152D80BF443A4E21145" }
这个字符串明显太长了
将
[2] => string(242) "3077020101042016DB22B45E332A719FB718D1E94F47A955443E4DB837EA37ACB0FE8E16059EBDA00A06082A811CCF550182xxxxxxxxxxxxxxxxxC8161D5FF03DD57A1DF5F1C04813CEB7A5EA8EE8F454E8FBA6393428B4118F29E1A43E3F7A9AA2086B072D152D80BF443A4E21145"
}
再asn1 一次就行了,我那测试的只解一层,私钥这个要再解一次,这串里有公钥 + 私钥 还有一个简单的方法就是用新版本的 openssl1.1.1w可能现在版本更高,支持国密了, 用openssl命令行直接就可以解出来了
还有: 不知道你这个是不是测试用的,如果是正式用的就不要全文发出来,不安全,我已把一些段给你隐了
感谢大佬, 公私钥都顺利转成16位了, 并与java 方的对上了
private function convertBase64PubKey2Hex(string $base64PubKey) {
$key = \Rtgm\util\MyAsn1::decode($base64PubKey, 'base64');
$key = $key[1];
if (substr($key, 0, 2) === '04') {
$key = substr($key, 2);
}
return $key;
}
private function convertBase64PriKey2Hex(string $base6PriKey) {
$key = \Rtgm\util\MyAsn1::decode($base6PriKey, 'base64');
$key = \Rtgm\util\MyAsn1::decode($key[2], 'hex');
$key = $key[1];
return $key;
}
^-^,好使就好
java开发中, 一般用到hutool工具中自带一个sm2整合工具, 使用的是base64格式的密钥
我在php中使用这个库时, 代码中要求的是 hex格式的密钥
所以需要把base64 转 hex
代码中提示使用 bin2hex(base64_decode($publicKey)) 可以转
但是我转出来的hex密钥却报 key format error
MFKWEWYHKOZIZJOCAQYIKOECZ1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxVAWPHV6HXWEgTZre60709FTO+ 6Y5NCIOEY8p4a0+P3qaoghByOVLYC/RDPOIRQ==
bin2hex(base64_decode($publicKey)) 后为
3059301306072a8643ce3d020106082xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxd5f103d57a1dts5f1c04813ceb7asea8e8f454e8ha6393428641829e1a43e31739a20856072d152d80bf43a4e2145
源码 ../RtSm2.php 第348行 _getKeyXY 方法中, 判断密钥格式 长度128, 或130以04开头, 否则都报format error, 明显我转出来的不能用
然后我看库说明 接收的是 base64 短串, 我不太懂 这个 “短串” 是什么意思, 难道我用的是长串