dcrypt_sign/ecdsa/
common.rs1use dcrypt_api::{error::Error as ApiError, Result as ApiResult};
4
5#[derive(Clone, Debug)]
7pub struct SignatureComponents {
8 pub r: Vec<u8>,
9 pub s: Vec<u8>,
10}
11
12impl SignatureComponents {
13 pub fn to_der(&self) -> Vec<u8> {
15 let mut der = Vec::new();
17
18 der.push(0x30);
20
21 let len_pos = der.len();
23 der.push(0x00);
24
25 der.push(0x02); let r_bytes = self.encode_integer(&self.r);
28 der.push(r_bytes.len() as u8);
29 der.extend_from_slice(&r_bytes);
30
31 der.push(0x02); let s_bytes = self.encode_integer(&self.s);
34 der.push(s_bytes.len() as u8);
35 der.extend_from_slice(&s_bytes);
36
37 let total_len = der.len() - len_pos - 1;
39 der[len_pos] = total_len as u8;
40
41 der
42 }
43
44 pub fn from_der(der: &[u8]) -> ApiResult<Self> {
46 if der.len() < 8 {
47 return Err(ApiError::InvalidSignature {
48 context: "ECDSA DER parsing",
49 #[cfg(feature = "std")]
50 message: "DER signature too short".to_string(),
51 });
52 }
53
54 if der[0] != 0x30 {
56 return Err(ApiError::InvalidSignature {
57 context: "ECDSA DER parsing",
58 #[cfg(feature = "std")]
59 message: "Invalid DER SEQUENCE tag".to_string(),
60 });
61 }
62
63 let mut pos = 2; if der[pos] != 0x02 {
67 return Err(ApiError::InvalidSignature {
68 context: "ECDSA DER parsing",
69 #[cfg(feature = "std")]
70 message: "Invalid DER INTEGER tag for r".to_string(),
71 });
72 }
73 pos += 1;
74 let r_len = der[pos] as usize;
75 pos += 1;
76 let r = der[pos..pos + r_len].to_vec();
77 pos += r_len;
78
79 if der[pos] != 0x02 {
81 return Err(ApiError::InvalidSignature {
82 context: "ECDSA DER parsing",
83 #[cfg(feature = "std")]
84 message: "Invalid DER INTEGER tag for s".to_string(),
85 });
86 }
87 pos += 1;
88 let s_len = der[pos] as usize;
89 pos += 1;
90 let s = der[pos..pos + s_len].to_vec();
91
92 Ok(SignatureComponents {
93 r: Self::decode_integer(&r),
94 s: Self::decode_integer(&s),
95 })
96 }
97
98 fn encode_integer(&self, bytes: &[u8]) -> Vec<u8> {
100 if bytes.is_empty() || bytes[0] & 0x80 == 0 {
101 bytes.to_vec()
102 } else {
103 let mut result = vec![0x00];
105 result.extend_from_slice(bytes);
106 result
107 }
108 }
109
110 fn decode_integer(bytes: &[u8]) -> Vec<u8> {
112 let mut result = bytes.to_vec();
113 while result.len() > 1 && result[0] == 0x00 {
114 result.remove(0);
115 }
116 result
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_der_encoding() {
126 let sig = SignatureComponents {
127 r: vec![0x01, 0x23, 0x45, 0x67],
128 s: vec![0x89, 0xAB, 0xCD, 0xEF],
129 };
130
131 let der = sig.to_der();
132 let parsed = SignatureComponents::from_der(&der).unwrap();
133
134 assert_eq!(sig.r, parsed.r);
135 assert_eq!(sig.s, parsed.s);
136 }
137
138 #[test]
139 fn test_der_with_high_bit() {
140 let sig = SignatureComponents {
142 r: vec![0xFF, 0x23, 0x45, 0x67],
143 s: vec![0x79, 0xAB, 0xCD, 0xEF],
144 };
145
146 let der = sig.to_der();
147
148 assert_eq!(der[3], 5); assert_eq!(der[4], 0x00); assert_eq!(der[5], 0xFF); let parsed = SignatureComponents::from_der(&der).unwrap();
155 assert_eq!(sig.r, parsed.r);
156 assert_eq!(sig.s, parsed.s);
157 }
158}