Closed honghuzhi closed 2 years ago
pem的base64_decode下, 用 asn1的编码方式解析出来就行了, 我这代码没有做这个用pem文件加解密的,只有hex的, 需要的话,你可以查看签名的那个,有从pem取出明文公私钥的方法
base64格式的一串公钥和 hex格式的一串公钥,怎么才能相互转化呢?试了下签名里面的方法,也是出错
HEX格式公钥,是ans1格式的二进制转成 16进制的吗?bin2hex 这个函数转换出来的长度好像也不对
$base64String = '*****';
$binaryData = base64_decode($base64String);
$asnObject = ASNObject::fromBinary($binaryData);
printObject($asnObject);
function printObject(ASNObject $object, $depth = 0){
$treeSymbol = '';
$depthString = str_repeat('─', $depth);
if ($depth > 0) {
$treeSymbol = '├';
}
$name = Identifier::getShortName($object->getType());
echo "{$treeSymbol}{$depthString}{$name} : ";
echo $object->__toString().PHP_EOL;
$content = $object->getContent();
if (is_array($content)) {
foreach ($object as $child) {
printObject($child, $depth + 1);
}
}
}
base64格式的sm2公钥转换后的hex公钥为130个字符,但私钥转换完却有242个字符,这是咋回事啊
gmp_init(): Unable to convert variable to GMP - string is not an integer // $encryptData = $c1.$c3.$c2 $adapter = $this->adapter; $generator = $this->generator; $this->cipher = new \Rtgm\smecc\SM2\Cipher(); $c1X = substr($encryptData,0,64); $c1Y = substr($encryptData,strlen($c1X),64); $c1Length = strlen($c1X) + strlen($c1Y); $c3 = substr($encryptData,$c1Length,64); $c2 = substr($encryptData,$c1Length+strlen($c3)); $p1 = new Point( $adapter, $generator->getCurve(), gmp_init($c1X, 16 ), gmp_init( $c1Y, 16 ) ); $this->cipher->initDecipher($p1,$privateKey);
$arrMsg = Hex2ByteBuf::HexStringToByteArray2($c2);
$arrMsg = $this->cipher->decryptBlock($arrMsg);
$document = hex2bin(Hex2ByteBuf::ByteArrayToHexString($arrMsg));
$c3_ = strtolower(Hex2ByteBuf::ByteArrayToHexString($this->cipher->Dofinal()));
if($c3 == $c3_){ //hash签名相同,
return $document;
私钥里是包含了公钥信息的,私钥里有 oid, 私钥,公钥, 公钥里只有 :oid, 公钥 ,
我的rtsm2文件 281行有从pem文件里解析出公钥的代码,同理也可以从文件里读出私钥的明文,这个只要操作一次就行,然后记下来
$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;
$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;
了解了,最好能封装个方法,方便外部直接调用导出
示例临时生成的公私钥
protected $publicKey = '3059301306072a8648ce3d020106082a811ccf5501822d03420004ab8e37df98b9dedf35771d01501596144aa06a80c7e90fe13a3933b373da9d0f3275403a294f1bf97d95705a7783cdb648c615410ed6088bafbe0e5a5f33af58';
protected $privateKey = '308193020100301306072a8648ce3d020106082a811ccf5501822d04793077020101042047d278e4fcc62df9d1af450adf9338b684f95467c3eb1f8d2d04d4915d4bc9f5a00a06082a811ccf5501822da14403420004ab8e37df98b9dedf35771d01501596144aa06a80c7e90fe13a3933b373da9d0f3275403a294f1bf97d95705a7783cdb648c615410ed6088bafbe0e5a5f33af58';
// https://the-x.cn/encodings/Asn1.aspx ASN.1解码工具 分析出来是以下这样
protected $publicKeyDecode = '04ab8e37df98b9dedf35771d01501596144aa06a80c7e90fe13a3933b373da9d0f3275403a294f1bf97d95705a7783cdb648c615410ed6088bafbe0e5a5f33af58';
protected $privateKeyDecode = '47D278E4FCC62DF9D1AF450ADF9338B684F95467C3EB1F8D2D04D4915D4BC9F5';
@honghuzhi @lpilp 您好,求助,最后如何解决的?我的私钥使用 MyAsn1 decode() 结果是 242位:
array:3 [
0 => "00"
1 => array:2 [
0 => "ecPublicKey"
1 => "sm2"
]
2 => "3077020101042047D278E4FCC62DF9D1AF450ADF9338B684F95467C3EB1F8D2D04D4915D4BC9F5A00A06082A811CCF5501822DA14403420004AB8E37DF98B9DEDF35771D01501596144AA06A80C7E90FE13A3933B373DA9D0F3275403A294F1BF97D95705A7783CDB648C615410ED6088BAFBE0E5A5F33AF58"
]
而且我将私钥转为pem格式,使用 doSignOutKey 签名报错 Invalid data
,使用公钥verifySignOutKey验签没问题
最后如何用代码实从原私钥获取到本扩展所能使用的公钥和私钥?
这个 myasn1 是简化版本的,不能递归全解出来,正常情况是公钥解一次, 私钥要解两次, 这是项目后面加的我写的简要功能, 不完善
array:3 [
0 => "00"
1 => array:2 [
0 => "ecPublicKey"
1 => "sm2"
]
2 => "3077020101042047D278E4FCC62DF9D1AF450ADF9338B684F95467C3EB1F8D2D04D4915D4BC9F5A00A06082A811CCF5501822DA14403420004AB8E37DF98B9DEDF35771D01501596144AA06A80C7E90FE13A3933B373DA9D0F3275403A294F1BF97D95705A7783CDB648C615410ED6088BAFBE0E5A5F33AF58"
]
将那个 array[2], 再解一次就出来私钥了,或者就直接调用
Array
(
[0] => 01
[1] => 47D278E4FCC62DF9D1AF450ADF9338B684F95467C3EB1F8D2D04D4915D4BC9F5
[2] => Array
(
)
[3] => Array
(
)
)
@lpilp 好的,感谢您的回复
有的银行提供的pem格式证书,如何转换成HEX格式呢?sm2加解密好像也没法直接读取pem格式吧