/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x509-parser-0.16.0/src/public_key.rs
Line | Count | Source |
1 | | use crate::error::*; |
2 | | use asn1_rs::FromDer; |
3 | | use der_parser::{ |
4 | | der::{parse_der_integer, parse_der_sequence_defined_g}, |
5 | | error::BerResult, |
6 | | }; |
7 | | |
8 | | /// Public Key value |
9 | | #[derive(Debug, PartialEq, Eq)] |
10 | | pub enum PublicKey<'a> { |
11 | | RSA(RSAPublicKey<'a>), |
12 | | EC(ECPoint<'a>), |
13 | | /// DSAPublicKey ::= INTEGER -- public key, Y (RFC 3279) |
14 | | DSA(&'a [u8]), |
15 | | /// GostR3410-94-PublicKey ::= OCTET STRING -- public key, Y (RFC 4491) |
16 | | GostR3410(&'a [u8]), |
17 | | /// GostR3410-2012-256-PublicKey ::= OCTET STRING (64), |
18 | | /// GostR3410-2012-512-PublicKey ::= OCTET STRING (128). (RFC 4491-bis) |
19 | | GostR3410_2012(&'a [u8]), |
20 | | |
21 | | Unknown(&'a [u8]), |
22 | | } |
23 | | |
24 | | impl<'a> PublicKey<'a> { |
25 | | /// Return the key size (in bits) or 0 |
26 | 0 | pub fn key_size(&self) -> usize { |
27 | 0 | match self { |
28 | 0 | Self::EC(ec) => ec.key_size(), |
29 | 0 | Self::RSA(rsa) => rsa.key_size(), |
30 | 0 | Self::DSA(y) | Self::GostR3410(y) => y.len() * 8, |
31 | 0 | _ => 0, |
32 | | } |
33 | 0 | } |
34 | | } |
35 | | |
36 | | /// RSA public Key, defined in rfc3279 |
37 | | #[derive(Debug, PartialEq, Eq)] |
38 | | pub struct RSAPublicKey<'a> { |
39 | | /// Raw bytes of the modulus |
40 | | /// |
41 | | /// This possibly includes a leading 0 if the MSB is 1 |
42 | | pub modulus: &'a [u8], |
43 | | /// Raw bytes of the exponent |
44 | | /// |
45 | | /// This possibly includes a leading 0 if the MSB is 1 |
46 | | pub exponent: &'a [u8], |
47 | | } |
48 | | |
49 | | impl<'a> RSAPublicKey<'a> { |
50 | | /// Attempt to convert exponent to u64 |
51 | | /// |
52 | | /// Returns an error if integer is too large, empty, or negative |
53 | 0 | pub fn try_exponent(&self) -> Result<u64, X509Error> { |
54 | 0 | let mut buf = [0u8; 8]; |
55 | 0 | if self.exponent.is_empty() || self.exponent[0] & 0x80 != 0 || self.exponent.len() > 8 { |
56 | 0 | return Err(X509Error::InvalidNumber); |
57 | 0 | } |
58 | 0 | buf[8_usize.saturating_sub(self.exponent.len())..].copy_from_slice(self.exponent); |
59 | 0 | let int = <u64>::from_be_bytes(buf); |
60 | 0 | Ok(int) |
61 | 0 | } |
62 | | |
63 | | /// Return the key size (in bits) or 0 |
64 | 0 | pub fn key_size(&self) -> usize { |
65 | 0 | if !self.modulus.is_empty() && self.modulus[0] & 0x80 == 0 { |
66 | | // XXX len must substract leading zeroes |
67 | 0 | let modulus = &self.modulus[1..]; |
68 | 0 | 8 * modulus.len() |
69 | | } else { |
70 | 0 | 0 |
71 | | } |
72 | 0 | } |
73 | | } |
74 | | |
75 | | // helper function to parse with error type BerError |
76 | 0 | fn parse_rsa_key(bytes: &[u8]) -> BerResult<RSAPublicKey> { |
77 | 0 | parse_der_sequence_defined_g(move |i, _| { |
78 | 0 | let (i, obj_modulus) = parse_der_integer(i)?; |
79 | 0 | let (i, obj_exponent) = parse_der_integer(i)?; |
80 | 0 | let modulus = obj_modulus.as_slice()?; |
81 | 0 | let exponent = obj_exponent.as_slice()?; |
82 | 0 | let key = RSAPublicKey { modulus, exponent }; |
83 | 0 | Ok((i, key)) |
84 | 0 | })(bytes) |
85 | 0 | } |
86 | | |
87 | | impl<'a> FromDer<'a, X509Error> for RSAPublicKey<'a> { |
88 | 0 | fn from_der(bytes: &'a [u8]) -> X509Result<'a, Self> { |
89 | 0 | parse_rsa_key(bytes).map_err(|_| nom::Err::Error(X509Error::InvalidSPKI)) |
90 | 0 | } |
91 | | } |
92 | | |
93 | | /// Elliptic Curve point, as defined in [RFC5480](https://datatracker.ietf.org/doc/html/rfc5480) |
94 | | #[derive(Debug, PartialEq, Eq)] |
95 | | pub struct ECPoint<'a> { |
96 | | data: &'a [u8], |
97 | | } |
98 | | |
99 | | impl<'a> ECPoint<'a> { |
100 | | /// EC Point content (See Standards for Efficient Cryptography Group (SECG), "SEC1: Elliptic Curve Cryptography") |
101 | 0 | pub fn data(&'a self) -> &'a [u8] { |
102 | 0 | self.data |
103 | 0 | } |
104 | | |
105 | | /// Return the key size (in bits) or 0 |
106 | 0 | pub fn key_size(&self) -> usize { |
107 | 0 | match self.data { |
108 | 0 | [] => { |
109 | | // empty |
110 | 0 | 0 |
111 | | } |
112 | 0 | [4, rem @ ..] => { |
113 | | // uncompressed |
114 | 0 | rem.len() * 8 / 2 |
115 | | } |
116 | 0 | [2..=3, rem @ ..] => { |
117 | | // compressed |
118 | 0 | rem.len() * 8 |
119 | | } |
120 | | _ => { |
121 | | // invalid |
122 | 0 | 0 |
123 | | } |
124 | | } |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl<'a> From<&'a [u8]> for ECPoint<'a> { |
129 | 0 | fn from(data: &'a [u8]) -> Self { |
130 | 0 | ECPoint { data } |
131 | 0 | } |
132 | | } |