75 lines
2.3 KiB
PHP
75 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace WeChatPay;
|
|
|
|
class RsaTool
|
|
{
|
|
/**
|
|
* @var string - Equal to `sequence(oid(1.2.840.113549.1.1.1), null))`
|
|
* @link https://datatracker.ietf.org/doc/html/rfc3447#appendix-A.2
|
|
*/
|
|
private const ASN1_OID_RSAENCRYPTION = '300d06092a864886f70d0101010500';
|
|
private const ASN1_SEQUENCE = 48;
|
|
private const CHR_NUL = "\0";
|
|
private const CHR_ETX = "\3";
|
|
|
|
/**
|
|
* Translate the \$thing strlen from `X690` style to the `ASN.1` 128bit hexadecimal length string
|
|
*
|
|
* @param string $thing - The string
|
|
*
|
|
* @return string The `ASN.1` 128bit hexadecimal length string
|
|
*/
|
|
private static function encodeLength(string $thing): string
|
|
{
|
|
$num = strlen($thing);
|
|
if ($num <= 0x7F) {
|
|
return sprintf('%c', $num);
|
|
}
|
|
|
|
$tmp = ltrim(pack('N', $num), self::CHR_NUL);
|
|
return pack('Ca*', strlen($tmp) | 0x80, $tmp);
|
|
}
|
|
|
|
/**
|
|
* Convert the `PKCS#1` format RSA Public Key to `SPKI` format
|
|
*
|
|
* @param string $thing - The base64-encoded string, without evelope style
|
|
*
|
|
* @return string The `SPKI` style public key without evelope string
|
|
*/
|
|
public static function pkcs1ToSpki(string $thing): string
|
|
{
|
|
$raw = self::CHR_NUL . base64_decode($thing);
|
|
$new = pack('H*', self::ASN1_OID_RSAENCRYPTION) . self::CHR_ETX . self::encodeLength($raw) . $raw;
|
|
|
|
return base64_encode(pack('Ca*a*', self::ASN1_SEQUENCE, self::encodeLength($new), $new));
|
|
}
|
|
|
|
public static function pemToBase64(string $data): string
|
|
{
|
|
$line = explode("\n", $data);
|
|
$base64 = '';
|
|
foreach($line as $row){
|
|
if(empty($row) || strpos($row, '-----BEGIN')!==false || strpos($row, '-----END')!==false) continue;
|
|
$base64 .= trim($row);
|
|
}
|
|
return $base64;
|
|
}
|
|
|
|
public static function base64ToPem(string $data, $type): string
|
|
{
|
|
if(empty($data) || strpos($data, '-----BEGIN')!==false) return $data;
|
|
$pem = "-----BEGIN ".$type."-----\n" .
|
|
wordwrap($data, 64, "\n", true) .
|
|
"\n-----END ".$type."-----";
|
|
return $pem;
|
|
}
|
|
|
|
public static function pkcs1ToSpkiPem(string $thing): string
|
|
{
|
|
$raw = self::pemToBase64($thing);
|
|
$new = self::pkcs1ToSpki($raw);
|
|
return self::base64ToPem($new, 'PUBLIC KEY');
|
|
}
|
|
} |