128 ? '81' : '').\dechex($Rl + $Sl + 4) .'02'.\dechex($Rl).$R .'02'.\dechex($Sl).$S ); return $der; } public static function fromDER(string $der, int $partLength): string { $hex = \unpack('H*', $der)[1]; if ('30' !== \mb_substr($hex, 0, 2, '8bit')) { // SEQUENCE throw new \RuntimeException(); } if ('81' === \mb_substr($hex, 2, 2, '8bit')) { // LENGTH > 128 $hex = \mb_substr($hex, 6, null, '8bit'); } else { $hex = \mb_substr($hex, 4, null, '8bit'); } if ('02' !== \mb_substr($hex, 0, 2, '8bit')) { // INTEGER throw new \RuntimeException(); } $Rl = \hexdec(\mb_substr($hex, 2, 2, '8bit')); $R = self::retrievePositiveInteger(\mb_substr($hex, 4, $Rl * 2, '8bit')); $R = \str_pad($R, $partLength, '0', STR_PAD_LEFT); $hex = \mb_substr($hex, 4 + $Rl * 2, null, '8bit'); if ('02' !== \mb_substr($hex, 0, 2, '8bit')) { // INTEGER throw new \RuntimeException(); } $Sl = \hexdec(\mb_substr($hex, 2, 2, '8bit')); $S = self::retrievePositiveInteger(\mb_substr($hex, 4, $Sl * 2, '8bit')); $S = \str_pad($S, $partLength, '0', STR_PAD_LEFT); return \pack('H*', $R.$S); } private static function preparePositiveInteger(string $data): string { if (\mb_substr($data, 0, 2, '8bit') > '7f') { return '00'.$data; } while ('00' === \mb_substr($data, 0, 2, '8bit') && \mb_substr($data, 2, 2, '8bit') <= '7f') { $data = \mb_substr($data, 2, null, '8bit'); } return $data; } private static function retrievePositiveInteger(string $data): string { while ('00' === \mb_substr($data, 0, 2, '8bit') && \mb_substr($data, 2, 2, '8bit') > '7f') { $data = \mb_substr($data, 2, null, '8bit'); } return $data; } }