Merge branch 'switch-rsa-to-pure-rust' into 'main'
Replace nettle with pure-rust RSA for conversions Closes #66 See merge request openpgp-card/openpgp-card!34
This commit is contained in:
commit
d2db840645
2 changed files with 148 additions and 11 deletions
|
@ -13,17 +13,18 @@ documentation = "https://docs.rs/crate/openpgp-card-sequoia"
|
|||
|
||||
[dependencies]
|
||||
sequoia-openpgp = "1.4"
|
||||
nettle = "7"
|
||||
openpgp-card = { path = "../openpgp-card", version = "0.3.3" }
|
||||
chrono = "0.4"
|
||||
anyhow = "1"
|
||||
thiserror = "1"
|
||||
log = "0.4"
|
||||
rsa = "0.8.1"
|
||||
|
||||
[dev-dependencies]
|
||||
openpgp-card-pcsc = { path = "../pcsc", version = "0.3" }
|
||||
#openpgp-card-scdc = { path = "../scdc", version = "0.3" }
|
||||
env_logger = "0.9"
|
||||
testresult = "0.3.0"
|
||||
|
||||
[[example]]
|
||||
name = "test"
|
||||
|
|
|
@ -109,6 +109,14 @@ impl CardUploadableKey for SequoiaKey {
|
|||
}
|
||||
}
|
||||
|
||||
fn mpi_to_biguint(mpi: &MPI) -> rsa::BigUint {
|
||||
slice_to_biguint(mpi.value())
|
||||
}
|
||||
|
||||
fn slice_to_biguint(bytes: &[u8]) -> rsa::BigUint {
|
||||
rsa::BigUint::from_bytes_be(bytes)
|
||||
}
|
||||
|
||||
/// RSA-specific data-structure to hold private (sub)key material for upload
|
||||
/// with the `openpgp-card` crate.
|
||||
struct SqRSA {
|
||||
|
@ -116,7 +124,9 @@ struct SqRSA {
|
|||
n: MPI,
|
||||
p: ProtectedMPI,
|
||||
q: ProtectedMPI,
|
||||
nettle: nettle::rsa::PrivateKey,
|
||||
pq: ProtectedMPI,
|
||||
dp1: ProtectedMPI,
|
||||
dq1: ProtectedMPI,
|
||||
}
|
||||
|
||||
impl SqRSA {
|
||||
|
@ -128,10 +138,43 @@ impl SqRSA {
|
|||
p: ProtectedMPI,
|
||||
q: ProtectedMPI,
|
||||
) -> Result<Self, Error> {
|
||||
let nettle = nettle::rsa::PrivateKey::new(d.value(), p.value(), q.value(), None)
|
||||
.map_err(|e| Error::InternalError(format!("nettle error {e:?}")))?;
|
||||
let key = rsa::RsaPrivateKey::from_components(
|
||||
mpi_to_biguint(&n),
|
||||
mpi_to_biguint(&e),
|
||||
slice_to_biguint(d.value()),
|
||||
vec![slice_to_biguint(p.value()), slice_to_biguint(q.value())],
|
||||
)
|
||||
.map_err(|e| Error::InternalError(format!("rsa error {e:?}")))?;
|
||||
|
||||
Ok(Self { e, n, p, q, nettle })
|
||||
let pq = key
|
||||
.qinv()
|
||||
.ok_or_else(|| Error::InternalError("pq value missing".into()))?
|
||||
.to_biguint()
|
||||
.ok_or_else(|| Error::InternalError("conversion to bigunit failed".into()))?
|
||||
.to_bytes_be()
|
||||
.into();
|
||||
|
||||
let dp1 = key
|
||||
.dp()
|
||||
.ok_or_else(|| Error::InternalError("dp1 value missing".into()))?
|
||||
.to_bytes_be()
|
||||
.into();
|
||||
|
||||
let dq1 = key
|
||||
.dq()
|
||||
.ok_or_else(|| Error::InternalError("dq1 value missing".into()))?
|
||||
.to_bytes_be()
|
||||
.into();
|
||||
|
||||
Ok(Self {
|
||||
e,
|
||||
n,
|
||||
p,
|
||||
q,
|
||||
pq,
|
||||
dp1,
|
||||
dq1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,16 +192,15 @@ impl RSAKey for SqRSA {
|
|||
}
|
||||
|
||||
fn pq(&self) -> Box<[u8]> {
|
||||
let (_, _, inv) = self.nettle.d_crt();
|
||||
inv
|
||||
self.pq.value().into()
|
||||
}
|
||||
|
||||
fn dp1(&self) -> Box<[u8]> {
|
||||
let (dp, _, _) = self.nettle.d_crt();
|
||||
dp
|
||||
self.dp1.value().into()
|
||||
}
|
||||
|
||||
fn dq1(&self) -> Box<[u8]> {
|
||||
let (_, dq, _) = self.nettle.d_crt();
|
||||
dq
|
||||
self.dq1.value().into()
|
||||
}
|
||||
|
||||
fn n(&self) -> &[u8] {
|
||||
|
@ -210,3 +252,97 @@ impl EccKey for SqEccKey {
|
|||
self.ecc_type
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use openpgp::cert::Cert;
|
||||
use openpgp::crypto::mpi::PublicKey;
|
||||
use openpgp::packet::key::SecretKeyMaterial;
|
||||
use openpgp::parse::Parse;
|
||||
use sequoia_openpgp as openpgp;
|
||||
use testresult::TestResult;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parsing_rsa_key() -> TestResult {
|
||||
let cert = Cert::from_bytes(
|
||||
r#"-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
lQHYBGPmItUBBADp/S0sPqOQF6oBEQf558E5HeVtRP0qyWaVT0/fl7gj2jMSu6kF
|
||||
de1jbr7AdeQxa7RiOo7m/ob8ZzKIzFNMLVfKsfo4mn5QjYulnadl+dyl87Jj1TlN
|
||||
iEmeVvKbJUzXf7p4B4zFBFwIoCWtGZMTuUOgvi11Gbt00QwNUZdB10VjNwARAQAB
|
||||
AAP/dH22pR3kSWL2oMRNX8XZJSn0pENh9RDCsRgE0HDU3IiPv8ZMviq5TjT+44tt
|
||||
2YrhCbxUk7zpEDUCbCepWrYCS7Q7pMCJul2AdymJBDkNwzrPjNdzPwx1mOIudDFp
|
||||
uosokjzx/bDNb9c8rdQpB5Oz9f9qZ9WhmfittQvBFPmBjyUCAPHWyhSVt86Wc3Dd
|
||||
/1nQRLwMHVJK6VszIMO0EYgGvaFN9WXh6VUue9DXnAkHejUDNpsOlJfiAHMDU0fS
|
||||
PnBX4D0CAPewtqGyIyluZ+S/+MJQBOUqLPzqHHr6smGmbOYFG52RFv17LhQH/02h
|
||||
sLkd6qXXNUFSOF02XiYV9RywhnSadIMCALP4oM2YGCQL+B5bj3bT1uwoF8O0gwuW
|
||||
FAc6Sz3ESpaI11ABLOv2wPNS3OcUyyIUe/DPVbekaKswvO57Ddzw5iait7QFQUJD
|
||||
REWIzgQTAQgAOBYhBBCVR7AQd8pmtyaMetgkYA0A8AOABQJj5iLVAhsBBQsJCAcC
|
||||
BhUKCQgLAgQWAgMBAh4BAheAAAoJENgkYA0A8AOA5W4EAMGuqrRLFjonYYS97Ypx
|
||||
zo7HUpOALrLVgfwKoxX2/DdC4FWOQ61cog63KKOiM/DjF/TimLD7R4wls6pbELyD
|
||||
T038FOlGoWtmtQuf3iUsBKdAYPPiqInaDU9XCy/hm1f7xOz70kpUXVG8K6c6my+b
|
||||
/fGkli/zcEWR55dOMPeoZ6zF
|
||||
=QZJ9
|
||||
-----END PGP PRIVATE KEY BLOCK-----"#,
|
||||
)?;
|
||||
if let Key::V4(key) = cert.primary_key().key().clone().parts_into_secret()? {
|
||||
let (e, n) = if let PublicKey::RSA { e, n } = key.mpis() {
|
||||
(e, n)
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
if let Some(SecretKeyMaterial::Unencrypted(secret)) = key.optional_secret() {
|
||||
assert!(secret.map(|secret| {
|
||||
if let openpgp::crypto::mpi::SecretKeyMaterial::RSA { d, p, q, .. } = secret {
|
||||
let rsa = SqRSA::new(e.clone(), d.clone(), n.clone(), p.clone(), q.clone())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
rsa.pq(),
|
||||
vec![
|
||||
66, 30, 140, 169, 99, 220, 224, 43, 7, 176, 133, 35, 251, 25, 162,
|
||||
178, 14, 200, 188, 60, 82, 126, 134, 117, 184, 10, 186, 28, 162,
|
||||
177, 225, 3, 147, 218, 96, 195, 182, 159, 32, 48, 87, 141, 182, 73,
|
||||
232, 37, 154, 152, 123, 11, 1, 86, 188, 224, 157, 35, 125, 4, 210,
|
||||
229, 233, 121, 207, 14
|
||||
]
|
||||
.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rsa.dp1(),
|
||||
vec![
|
||||
19, 67, 44, 109, 95, 79, 120, 160, 251, 40, 238, 69, 188, 125, 158,
|
||||
59, 236, 43, 25, 182, 229, 199, 97, 215, 38, 63, 93, 118, 28, 51,
|
||||
86, 121, 195, 38, 14, 76, 107, 128, 124, 84, 50, 24, 55, 143, 228,
|
||||
231, 252, 13, 137, 100, 43, 233, 189, 18, 148, 22, 155, 183, 136,
|
||||
195, 120, 103, 71, 113
|
||||
]
|
||||
.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rsa.dq1(),
|
||||
vec![
|
||||
29, 192, 92, 47, 143, 246, 41, 67, 217, 182, 224, 88, 64, 254, 219,
|
||||
151, 171, 57, 60, 39, 226, 195, 226, 217, 10, 97, 179, 50, 237,
|
||||
234, 35, 67, 10, 63, 232, 75, 224, 156, 21, 78, 125, 221, 124, 94,
|
||||
219, 144, 144, 9, 21, 143, 138, 181, 167, 146, 39, 128, 251, 176,
|
||||
54, 131, 239, 253, 157, 129
|
||||
]
|
||||
.into()
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue