diff options
Diffstat (limited to 'vendor/web-token/jwt-core/Util/ECSignature.php')
-rw-r--r-- | vendor/web-token/jwt-core/Util/ECSignature.php | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/vendor/web-token/jwt-core/Util/ECSignature.php b/vendor/web-token/jwt-core/Util/ECSignature.php new file mode 100644 index 0000000..5bfa5b0 --- /dev/null +++ b/vendor/web-token/jwt-core/Util/ECSignature.php @@ -0,0 +1,93 @@ +<?php + +declare(strict_types=1); + +/* + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Spomky-Labs + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +namespace Jose\Component\Core\Util; + +/** + * @internal + */ +class ECSignature +{ + public static function toDER(string $signature, int $partLength): string + { + $signature = \unpack('H*', $signature)[1]; + if (\mb_strlen($signature, '8bit') !== 2 * $partLength) { + throw new \InvalidArgumentException('Invalid length.'); + } + $R = \mb_substr($signature, 0, $partLength, '8bit'); + $S = \mb_substr($signature, $partLength, null, '8bit'); + + $R = self::preparePositiveInteger($R); + $Rl = \mb_strlen($R, '8bit') / 2; + $S = self::preparePositiveInteger($S); + $Sl = \mb_strlen($S, '8bit') / 2; + $der = \pack('H*', + '30'.($Rl + $Sl + 4 > 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; + } +} |