@@ -264,10 +264,15 @@ private bool VerifyEcdsaSignature(byte[] publicKeyBytes, HashAlgorithmName hashA
264264 {
265265 ecdsa . ImportSubjectPublicKeyInfo ( m_subjectPublicKeyInfo , out _ ) ;
266266
267+ // PKCS#10 CSRs store ECDSA signatures in DER format (ASN.1 SEQUENCE)
268+ // but .NET's VerifyData expects IEEE P1363 format (r || s)
269+ // We need to convert the signature format
270+ byte [ ] ieee1363Signature = ConvertEcdsaSignatureDerToIeee1363 ( m_signature ) ;
271+
267272 // Verify signature
268273 return ecdsa . VerifyData (
269274 m_certificationRequestInfo ,
270- m_signature ,
275+ ieee1363Signature ,
271276 hashAlgorithm ) ;
272277 }
273278 catch
@@ -282,5 +287,49 @@ private bool VerifyEcdsaSignature(byte[] publicKeyBytes, HashAlgorithmName hashA
282287 "Please use .NET 6.0 or later." ) ;
283288#endif
284289 }
290+
291+ /// <summary>
292+ /// Converts ECDSA signature from DER format to IEEE P1363 format.
293+ /// </summary>
294+ /// <param name="derSignature">DER-encoded signature (SEQUENCE { r INTEGER, s INTEGER })</param>
295+ /// <returns>IEEE P1363 format signature (r || s)</returns>
296+ private static byte [ ] ConvertEcdsaSignatureDerToIeee1363 ( byte [ ] derSignature )
297+ {
298+ // Parse DER SEQUENCE
299+ var reader = new AsnReader ( derSignature , AsnEncodingRules . DER ) ;
300+ AsnReader sequenceReader = reader . ReadSequence ( ) ;
301+
302+ // Read r and s as integers
303+ byte [ ] r = sequenceReader . ReadIntegerBytes ( ) . ToArray ( ) ;
304+ byte [ ] s = sequenceReader . ReadIntegerBytes ( ) . ToArray ( ) ;
305+
306+ // Remove leading zero bytes that may be present for sign bit
307+ r = TrimLeadingZero ( r ) ;
308+ s = TrimLeadingZero ( s ) ;
309+
310+ // Determine the key size (both r and s should be the same size)
311+ int keySize = Math . Max ( r . Length , s . Length ) ;
312+
313+ // Pad to the correct size
314+ byte [ ] ieee1363Signature = new byte [ keySize * 2 ] ;
315+ Array . Copy ( r , 0 , ieee1363Signature , keySize - r . Length , r . Length ) ;
316+ Array . Copy ( s , 0 , ieee1363Signature , keySize * 2 - s . Length , s . Length ) ;
317+
318+ return ieee1363Signature ;
319+ }
320+
321+ /// <summary>
322+ /// Removes leading zero byte if present (used for sign bit in ASN.1 INTEGER encoding).
323+ /// </summary>
324+ private static byte [ ] TrimLeadingZero ( byte [ ] data )
325+ {
326+ if ( data . Length > 1 && data [ 0 ] == 0 && ( data [ 1 ] & 0x80 ) != 0 )
327+ {
328+ byte [ ] trimmed = new byte [ data . Length - 1 ] ;
329+ Array . Copy ( data , 1 , trimmed , 0 , trimmed . Length ) ;
330+ return trimmed ;
331+ }
332+ return data ;
333+ }
285334 }
286335}
0 commit comments