[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 declare(strict_types=1); 4 5 /* 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2014-2019 Spomky-Labs 9 * 10 * This software may be modified and distributed under the terms 11 * of the MIT license. See the LICENSE file for details. 12 */ 13 14 namespace Cose\Algorithm\Signature\ECDSA; 15 16 use InvalidArgumentException; 17 use const STR_PAD_LEFT; 18 19 /** 20 * @internal 21 */ 22 final class ECSignature 23 { 24 private const ASN1_SEQUENCE = '30'; 25 private const ASN1_INTEGER = '02'; 26 private const ASN1_MAX_SINGLE_BYTE = 128; 27 private const ASN1_LENGTH_2BYTES = '81'; 28 private const ASN1_BIG_INTEGER_LIMIT = '7f'; 29 private const ASN1_NEGATIVE_INTEGER = '00'; 30 private const BYTE_SIZE = 2; 31 32 public static function toAsn1(string $signature, int $length): string 33 { 34 $signature = bin2hex($signature); 35 36 if (self::octetLength($signature) !== $length) { 37 throw new InvalidArgumentException('Invalid signature length.'); 38 } 39 40 $pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit')); 41 $pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit')); 42 43 $lengthR = self::octetLength($pointR); 44 $lengthS = self::octetLength($pointS); 45 46 $totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE; 47 $lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : ''; 48 49 return self::hex2bin( 50 self::ASN1_SEQUENCE 51 .$lengthPrefix.dechex($totalLength) 52 .self::ASN1_INTEGER.dechex($lengthR).$pointR 53 .self::ASN1_INTEGER.dechex($lengthS).$pointS 54 ); 55 } 56 57 public static function fromAsn1(string $signature, int $length): string 58 { 59 $message = bin2hex($signature); 60 $position = 0; 61 62 if (self::ASN1_SEQUENCE !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { 63 throw new InvalidArgumentException('Invalid data. Should start with a sequence.'); 64 } 65 66 if (self::ASN1_LENGTH_2BYTES === self::readAsn1Content($message, $position, self::BYTE_SIZE)) { 67 $position += self::BYTE_SIZE; 68 } 69 70 $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); 71 $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); 72 73 return self::hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT).str_pad($pointS, $length, '0', STR_PAD_LEFT)); 74 } 75 76 private static function octetLength(string $data): int 77 { 78 return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE); 79 } 80 81 private static function preparePositiveInteger(string $data): string 82 { 83 if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { 84 return self::ASN1_NEGATIVE_INTEGER.$data; 85 } 86 87 while (self::ASN1_NEGATIVE_INTEGER === mb_substr($data, 0, self::BYTE_SIZE, '8bit') 88 && mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) { 89 $data = mb_substr($data, 2, null, '8bit'); 90 } 91 92 return $data; 93 } 94 95 private static function readAsn1Content(string $message, int &$position, int $length): string 96 { 97 $content = mb_substr($message, $position, $length, '8bit'); 98 $position += $length; 99 100 return $content; 101 } 102 103 private static function readAsn1Integer(string $message, int &$position): string 104 { 105 if (self::ASN1_INTEGER !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { 106 throw new InvalidArgumentException('Invalid data. Should contain an integer.'); 107 } 108 109 $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE)); 110 111 return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE); 112 } 113 114 private static function retrievePositiveInteger(string $data): string 115 { 116 while (self::ASN1_NEGATIVE_INTEGER === mb_substr($data, 0, self::BYTE_SIZE, '8bit') 117 && mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { 118 $data = mb_substr($data, 2, null, '8bit'); 119 } 120 121 return $data; 122 } 123 124 private static function hex2bin(string $data): string 125 { 126 $result = \hex2bin($data); 127 if (false === $result) { 128 throw new InvalidArgumentException('Unable to convert the data'); 129 } 130 131 return $result; 132 } 133 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |