@@ -234,7 +234,7 @@ public function __construct($type, $params=null)
234234 }
235235 throw new Exception ('Certificate "type" (private/public) must be passed via parameters ' );
236236 case (self ::ECDSA_SHA256 ):
237- $ this ->cryptParams ['library ' ] = 'openssl ' ;
237+ $ this ->cryptParams ['library ' ] = 'phpseclib ' ;
238238 $ this ->cryptParams ['method ' ] = 'http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256 ' ;
239239 $ this ->cryptParams ['digest ' ] = 'SHA256 ' ;
240240 if (is_array ($ params ) && ! empty ($ params ['type ' ])) {
@@ -591,9 +591,6 @@ private function signOpenSSL($data)
591591 if (! openssl_sign ($ data , $ signature , $ this ->key , $ algo )) {
592592 throw new Exception ('Failure Signing Data: ' . openssl_error_string () . ' - ' . $ algo );
593593 }
594- if ($ this ->type === self ::ECDSA_SHA256 ) {
595- $ signature = $ this ->derToRawEcdsa ($ signature , 32 );
596- }
597594 return $ signature ;
598595 }
599596
@@ -619,9 +616,6 @@ private function verifyOpenSSL($data, $signature)
619616 if (! empty ($ this ->cryptParams ['digest ' ])) {
620617 $ algo = $ this ->cryptParams ['digest ' ];
621618 }
622- if ($ this ->type === self ::ECDSA_SHA256 ) {
623- $ signature = $ this ->rawToDerEcdsa ($ signature );
624- }
625619 return openssl_verify ($ data , $ signature , $ this ->key , $ algo );
626620 }
627621
@@ -693,6 +687,12 @@ public function signData($data)
693687 return $ this ->signOpenSSL ($ data );
694688 case 'phpseclib ' :
695689 $ private = PublicKeyLoader::load ($ this ->key );
690+ if ($ this ->type === self ::ECDSA_SHA256 ) {
691+ return $ private
692+ ->withHash ($ this ->cryptParams ['digest ' ])
693+ ->withSignatureFormat ('IEEE ' )
694+ ->sign ($ data );
695+ }
696696 return $ private
697697 ->withPadding ($ this ->cryptParams ['padding ' ])
698698 ->withHash ($ this ->cryptParams ['digest ' ])
@@ -726,6 +726,13 @@ public function verifySignature($data, $signature)
726726 return $ this ->verifyOpenSSL ($ data , $ signature );
727727 case 'phpseclib ' :
728728 $ public = PublicKeyLoader::load ($ this ->key );
729+ if ($ this ->type === self ::ECDSA_SHA256 ) {
730+ $ result = $ public
731+ ->withHash ($ this ->cryptParams ['digest ' ])
732+ ->withSignatureFormat ('IEEE ' )
733+ ->verify ($ data , $ signature );
734+ return $ result === true ? 1 : 0 ;
735+ }
729736 $ result = $ public
730737 ->withPadding ($ this ->cryptParams ['padding ' ])
731738 ->withHash ($ this ->cryptParams ['digest ' ])
@@ -874,85 +881,4 @@ public static function fromEncryptedKeyElement(DOMElement $element)
874881 return $ objKey ;
875882 }
876883
877- /**
878- * Converts ASN.1 DER ECDSA signature to RAW (IEEE P1363) format
879- *
880- * @param string $derSignature
881- * @param int $curveByteSize
882- * @return string
883- * @throws Exception
884- */
885- private function derToRawEcdsa ($ derSignature , $ curveByteSize = 32 ) {
886- $ offset = 0 ;
887-
888- // 1. SEQUENCE (0x30) check
889- if (ord ($ derSignature [$ offset ++]) !== 0x30 ) {
890- throw new Exception ("Invalid DER signature. " );
891- }
892-
893- $ offset ++; // Skip total length
894-
895- // 2. R value (0x02)
896- if (ord ($ derSignature [$ offset ++]) !== 0x02 ) {
897- throw new Exception ("Invalid DER format (missing R). " );
898- }
899- $ rLen = ord ($ derSignature [$ offset ++]);
900- $ r = substr ($ derSignature , $ offset , $ rLen );
901- $ offset += $ rLen ;
902-
903- // 3. S value (0x02)
904- if (ord ($ derSignature [$ offset ++]) !== 0x02 ) {
905- throw new Exception ("Invalid DER format (missing S). " );
906- }
907- $ sLen = ord ($ derSignature [$ offset ++]);
908- $ s = substr ($ derSignature , $ offset , $ sLen );
909-
910- // 4. Clean up DER padding (leading 0x00 bytes) if any
911- $ r = ltrim ($ r , "\x00" );
912- $ s = ltrim ($ s , "\x00" );
913-
914- // 5. Adjust to curve size (32 bytes) with padding
915- $ r = str_pad ($ r , $ curveByteSize , "\x00" , STR_PAD_LEFT );
916- $ s = str_pad ($ s , $ curveByteSize , "\x00" , STR_PAD_LEFT );
917-
918- // 6. Concat and return
919- return $ r . $ s ;
920- }
921-
922- /**
923- * Converts RAW (IEEE P1363) ECDSA signature to ASN.1 DER format
924- *
925- * @param string $rawSignature
926- * @return string
927- * @throws Exception
928- */
929- private function rawToDerEcdsa ($ rawSignature ) {
930- // P-256 RAW signature should be exactly 64 bytes
931- if (strlen ($ rawSignature ) !== 64 ) {
932- throw new Exception ("Invalid RAW signature length. Expected 64 bytes for P-256. " );
933- }
934-
935- $ r = substr ($ rawSignature , 0 , 32 );
936- $ s = substr ($ rawSignature , 32 , 32 );
937-
938- // Remove leading zeros
939- $ r = ltrim ($ r , "\x00" );
940- $ s = ltrim ($ s , "\x00" );
941-
942- // If high bit is set, prepend 0x00 to make it positive integer in ASN.1
943- if (ord ($ r [0 ]) >= 0x80 ) {
944- $ r = "\x00" . $ r ;
945- }
946- if (ord ($ s [0 ]) >= 0x80 ) {
947- $ s = "\x00" . $ s ;
948- }
949-
950- $ rDer = chr (0x02 ) . chr (strlen ($ r )) . $ r ;
951- $ sDer = chr (0x02 ) . chr (strlen ($ s )) . $ s ;
952-
953- $ sequence = $ rDer . $ sDer ;
954-
955- return chr (0x30 ) . chr (strlen ($ sequence )) . $ sequence ;
956- }
957-
958884}
0 commit comments