1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use log::trace;
use openssl::pkey::PKey;
use crate::Error;
use crate::utils;
pub fn verify_dss(dss: &[u8], pub_key: &PKey<openssl::pkey::Public>, data: &[u8]) -> Result<(), Error> {
if dss.len() > (1usize << 16usize) + 3 {
return Err(Error::InvalidSignature(format!("dss too long. (len = {})", dss.len())));
}
if dss.len() < 4 {
return Err(Error::InvalidSignature(format!("Invalid dss: {}\n Too short. Expected at least 4 bytes.", &utils::u8_to_hex(dss))));
}
let sig_type = u16::from_be_bytes([dss[0], dss[1]]);
let length = u16::from_be_bytes([dss[2], dss[3]]);
let rest = &dss[4..];
if rest.len() != length as usize {
return Err(Error::InvalidSignature(format!("Invalid dss: {}\n It says there that there are {} bytes in the signature part, but I see {}.", &utils::u8_to_hex(dss), length, rest.len())));
}
const SIGSCHEME_ECDSA_NISTP256_SHA256: u16 = 0x0403;
const SIGSCHEME_RSA_PKCS1_SHA256: u16 = 0x0401;
match sig_type {
SIGSCHEME_ECDSA_NISTP256_SHA256 => {
if pub_key.id() != openssl::pkey::Id::EC {
return Err(Error::InvalidSignature(format!("dss says signature is EC, but key is {:?}", pub_key.id())));
}
}
SIGSCHEME_RSA_PKCS1_SHA256 => {
if pub_key.id() != openssl::pkey::Id::RSA {
return Err(Error::InvalidSignature(format!("dss says signature is RSA, but key is {:?}", pub_key.id())));
}
}
_ => {
return Err(Error::InvalidSignature(format!("Unknow signature scheme {:2x}", sig_type)));
}
}
let mut verifier = openssl::sign::Verifier::new(openssl::hash::MessageDigest::sha256(), pub_key).map_err(|e| Error::Unknown(format!("EVP_DigestVerifyInit: {}", &e)))?;
if sig_type == SIGSCHEME_RSA_PKCS1_SHA256 {
verifier.set_rsa_padding(openssl::rsa::Padding::PKCS1).map_err(|e| Error::Unknown(format!("EVP_PKEY_CTX_set_rsa_padding: {}", &e)))?;
}
verifier.update(data).map_err(|e| Error::Unknown(format!("EVP_DigestUpdate: {}", &e)))?;
if !verifier.verify(rest).map_err(|e| Error::InvalidSignature(format!("EVP_DigestVerifyFinal: {}", &e)))? {
return Err(Error::InvalidSignature(format!("Signature is invalid: signature = {}, data = {}.", &utils::u8_to_hex(rest), &utils::u8_to_hex(data))));
}
trace!("Signature checked for data {} - signature is {}", &utils::u8_to_hex(data), &utils::u8_to_hex(dss));
Ok(())
}
#[test]
fn verify_dss_test() {
let key = PKey::public_key_from_der(&utils::hex_to_u8("3056301006072a8648ce3d020106052b8104000a0342000412c022d1b5cab048f419d46f111743cea4fcd54a05228d14cecd9cc1d120e4cc3e22e8481e5ccc3db16273a8d981ac144306d644a4227468fccd6580563ec8bd")[..]).unwrap();
verify_dss(&utils::hex_to_u8("040300473045022100ba6da0fb4d4440965dd1d096212da95880320113320ddc5202a0b280ac518349022005bb17637d4ed06facb4af5b4b9b9083210474998ac33809a6e10c9352032055"), &key, b"hello").unwrap();
verify_dss(&utils::hex_to_u8("0403004830460221009857dc5e2bcc0b67059a5bde9ead6a36614ab315423c0b2e4762ba7aca3f0181022100eab3af33367cb89d556c17c1ce7de1c2b8c2b80d709d0c3cbb45c8acc6809d1d"), &key, b"not hello").unwrap();
verify_dss(&utils::hex_to_u8("0403004830460221009857dc5e2bcc0b67059a5bde9ead6a36614ab315423c0b2e4762ba7aca3f0181022100eab3af33367cb89d556c17c1ce7de1c2b8c2b80d709d0c3cbb45c8acc6809d1d"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8(""), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("00"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("0001"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("000102"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("00010203"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("0001020304"), &key, b"hello").expect_err("");
verify_dss(&utils::hex_to_u8("000102030405"), &key, b"hello").expect_err("");
}