public static function fromDER(string $der, int $partLength) { $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); } /** * @param string $data * * @return string */ private static function retrievePositiveInteger(string $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; }