@@ -14,7 +14,7 @@ use windows_sys::Win32::Security::Cryptography::{
1414use crate :: key:: { AlgorithmGroup , NCryptKey , SignaturePadding } ;
1515
1616// Convert IEEE-P1363 signature format to DER encoding.
17- // Some modifications are taken from https://github.com/tofay/rustls-cng-crypto/blob/main/src/signer/ec.rs
17+ // The maximum signature size we support is 132 bytes of the NIST P-521 curve.
1818fn p1363_to_der ( data : & [ u8 ] ) -> Vec < u8 > {
1919 const SEQUENCE_TAG : u8 = 0x30 ;
2020 const INTEGER_TAG : u8 = 0x02 ;
@@ -34,24 +34,14 @@ fn p1363_to_der(data: &[u8]) -> Vec<u8> {
3434
3535 let v_length = 4 + r_sign. len ( ) + s_sign. len ( ) + r. len ( ) + s. len ( ) ;
3636
37- let ( short_form, length_len) = if v_length <= 0x80 {
38- ( true , 1 )
39- } else {
40- let mut v_length = v_length;
41- let mut length_len = 0 ;
42- while v_length > 0 {
43- v_length >>= 8 ;
44- length_len += 1 ;
45- }
46- ( false , length_len)
47- } ;
37+ let length_len = ( usize:: BITS - v_length. leading_zeros ( ) ) . div_ceil ( 8 ) as usize ;
4838
49- let length = length_len + v_length + 1 ;
50- let mut der = Vec :: with_capacity ( length) ;
39+ let mut der = Vec :: with_capacity ( 1 + length_len + v_length) ;
5140
5241 der. push ( SEQUENCE_TAG ) ;
53- if short_form {
54- der. push ( v_length as u8 ) ; // LENGTH - short form
42+
43+ if v_length < 128 {
44+ der. push ( v_length as u8 ) ;
5545 } else {
5646 der. push ( 0x80 | length_len as u8 ) ;
5747 for i in ( 0 ..length_len) . rev ( ) {
@@ -219,20 +209,69 @@ impl SigningKey for CngSigningKey {
219209
220210#[ cfg( test) ]
221211mod tests {
212+ use der:: { Decode , Reader , asn1:: Int } ;
213+
214+ fn validate_der ( data : & [ u8 ] , r : & Int , s : & Int ) {
215+ let ( decoded_r, decoded_s) = der:: SliceReader :: new ( & data)
216+ . unwrap ( )
217+ . sequence ( |reader| Ok ( ( Int :: decode ( reader) ?, Int :: decode ( reader) ?) ) )
218+ . unwrap ( ) ;
219+
220+ assert_eq ! ( decoded_r, * r) ;
221+ assert_eq ! ( decoded_s, * s) ;
222+ }
223+
222224 #[ test]
223225 fn test_p1363_to_der ( ) {
224226 let p1363 = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
225227 let der = super :: p1363_to_der ( & p1363) ;
226- assert_eq ! ( der, [ 0x30 , 0x0c , 0x02 , 0x04 , 1 , 2 , 3 , 4 , 0x02 , 0x04 , 5 , 6 , 7 , 8 ] )
228+ validate_der (
229+ & der,
230+ & Int :: new ( & [ 1 , 2 , 3 , 4 ] ) . unwrap ( ) ,
231+ & Int :: new ( & [ 5 , 6 , 7 , 8 ] ) . unwrap ( ) ,
232+ ) ;
227233 }
228234
229235 #[ test]
230236 fn test_p1363_to_der_signed ( ) {
231237 let p1363 = [ 0x81 , 2 , 3 , 4 , 0x85 , 6 , 7 , 8 ] ;
232238 let der = super :: p1363_to_der ( & p1363) ;
233- assert_eq ! (
234- der,
235- [ 0x30 , 0x0e , 0x02 , 0x05 , 0 , 0x81 , 2 , 3 , 4 , 0x02 , 0x05 , 0 , 0x85 , 6 , 7 , 8 ]
236- )
239+ validate_der (
240+ & der,
241+ & Int :: new ( & [ 0 , 0x81 , 2 , 3 , 4 ] ) . unwrap ( ) ,
242+ & Int :: new ( & [ 0 , 0x85 , 6 , 7 , 8 ] ) . unwrap ( ) ,
243+ ) ;
244+ }
245+
246+ #[ test]
247+ fn test_p1363_to_der_zeroes_stripped ( ) {
248+ let p1363 = [ 0 , 1 , 2 , 3 , 4 , 0 , 5 , 6 , 7 , 8 ] ;
249+ let der = super :: p1363_to_der ( & p1363) ;
250+ validate_der (
251+ & der,
252+ & Int :: new ( & [ 1 , 2 , 3 , 4 ] ) . unwrap ( ) ,
253+ & Int :: new ( & [ 5 , 6 , 7 , 8 ] ) . unwrap ( ) ,
254+ ) ;
255+ }
256+
257+ #[ test]
258+ fn test_p1363_to_der_signed_zeroes_stripped ( ) {
259+ let p1363 = [ 0 , 0x81 , 2 , 3 , 4 , 0 , 0x85 , 6 , 7 , 8 ] ;
260+ let der = super :: p1363_to_der ( & p1363) ;
261+ validate_der (
262+ & der,
263+ & Int :: new ( & [ 0 , 0x81 , 2 , 3 , 4 ] ) . unwrap ( ) ,
264+ & Int :: new ( & [ 0 , 0x85 , 6 , 7 , 8 ] ) . unwrap ( ) ,
265+ ) ;
266+ }
267+
268+ #[ test]
269+ fn test_p1363_to_der_long ( ) {
270+ let r = ( 1 ..128 ) . collect :: < Vec < u8 > > ( ) ;
271+ let s = ( 1 ..128 ) . rev ( ) . collect :: < Vec < u8 > > ( ) ;
272+
273+ let p1363 = r. clone ( ) . into_iter ( ) . chain ( s. clone ( ) ) . collect :: < Vec < u8 > > ( ) ;
274+ let der = super :: p1363_to_der ( & p1363) ;
275+ validate_der ( & der, & Int :: new ( & r) . unwrap ( ) , & Int :: new ( & s) . unwrap ( ) ) ;
237276 }
238277}
0 commit comments