-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using a simple self-signed certificate with native-tls identity #91
Comments
First, what's your OS? And OS version? Does your OS support P-256? |
Apologies realised I did not add that info initially; Windows 10 and Windows 11 on two machines, I believe it does support it? |
Can you try with an existing key, different algorithms, and maybe generally with some variations in which features to enable etc.? Maybe with a little bit of debugging we can find the cause. I don't have access to windows 10 environment atm. |
Will do and report back! |
Here's what I've tried so far: All combinations of: Algorithm Options:
Certificate Authority Options:
Key Id Method Options:
The outcomes only vary by Algorithm (regardless of CA and KId options):
Does this highlight anything else I can test over? Updated [dependencies]
rcgen = { version = "0.9.3", features = ["pem", "x509-parser"]}
native-tls = "0.2.10"
tabled = "0.8.0" Updated use tabled::{Table, Tabled};
fn make_identity(
alg: &'static rcgen::SignatureAlgorithm,
ca_option: rcgen::IsCa,
kid_option: rcgen::KeyIdMethod,
) -> Result<native_tls::Identity, String> {
let mut certificate_parameters = rcgen::CertificateParams::new(["localhost".to_string()]);
certificate_parameters.alg = alg;
certificate_parameters.is_ca = ca_option;
certificate_parameters.key_identifier_method = kid_option;
let test_certificate = rcgen::Certificate::from_params(certificate_parameters)
.map_err(|err| format!("Certificate::from_params: \n {:#?}", err))?;
// Serialises the certificate to PKCS#8 PEM
let pem = test_certificate.serialize_pem().unwrap();
// Serialises to PKCS#8 format in PEM
let pkey = test_certificate.get_key_pair().serialize_pem();
native_tls::Identity::from_pkcs8(pem.as_bytes(), pkey.as_bytes())
.map_err(|err| format!("Identity::from_pkcs8: \n {:#?}", err))
}
// Output helpers
#[derive(Tabled)]
struct CombinationCheck<'a> {
algorithm: &'a str,
ca_option: &'a str,
key_id_option: &'a str,
error: String,
}
fn main() {
// Algorithms
let algorithms = &[
(&rcgen::PKCS_RSA_SHA256, "PKCS_RSA_SHA256"),
(&rcgen::PKCS_RSA_SHA384, "PKCS_RSA_SHA384"),
(&rcgen::PKCS_RSA_SHA512, "PKCS_RSA_SHA512"),
(&rcgen::PKCS_ECDSA_P256_SHA256, "PKCS_ECDSA_P256_SHA256"),
(&rcgen::PKCS_ECDSA_P384_SHA384, "PKCS_ECDSA_P384_SHA384"),
(&rcgen::PKCS_ED25519, "PKCS_ED25519")
];
// Ca options
let ca_options = &[
(rcgen::IsCa::SelfSignedOnly, "IsCa::SelfSignedOnly"),
(rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained), "IsCa::Ca(rcgen::BasicConstraints::Unconstrained)")
];
// Key Is Method options
let key_id_options = &[
(rcgen::KeyIdMethod::Sha256, "Sha256"),
(rcgen::KeyIdMethod::Sha384, "Sha384"),
(rcgen::KeyIdMethod::Sha512, "Sha512"),
];
let mut tests = vec![];
for (alg, name) in algorithms {
for (ca_option, ca_option_name) in ca_options {
for (kid_option, kid_name) in key_id_options {
let mut outcome = CombinationCheck {
algorithm: name,
ca_option: ca_option_name,
key_id_option: kid_name,
error: "".to_string(),
};
match make_identity(
alg,
ca_option.clone(),
kid_option.clone()) {
Err(err_str) => { outcome.error = format!("{} failed: \n {}", name, err_str).to_string() }
_ => ()
};
tests.push(outcome);
}
}
};
let table = Table::new(tests).to_string();
println!("{}", table);
} |
Comparing certificates:Generated using openssl req -x509 -nodes -days 365 -newkey rsa:512 -keyout selfsigned.key.pem -out selfsigned-x509.crt -subj "/CN=localhost"
Test: use std::fs;
use std::io::Read;
fn main() {
let mut crt = vec![];
let mut pkey = vec![];
fs::File::open("selfsigned-x509.crt").unwrap()
.read_to_end(&mut crt).unwrap();
fs::File::open("selfsigned.key.pem").unwrap()
.read_to_end(&mut pkey).unwrap();
let identity = native_tls::Identity::from_pkcs8(&crt, &pkey).unwrap();
// Does not panic
}
|
Can you try loading the key via rcgen, to test whether key generation is the cause of the issue? |
Do you mean as follows: use std::fs;
use std::io::Read;
fn main() {
let mut pkey = vec![];
let mut crt = vec![];
fs::File::open("selfsigned.key.pem").unwrap()
.read_to_end(&mut pkey).unwrap();
fs::File::open("selfsigned-x509.crt").unwrap()
.read_to_end(&mut crt).unwrap();
let key_pair = rcgen::KeyPair::from_pem(
&String::from_utf8(pkey).unwrap()
).unwrap();
/* ^This Panics^:
CouldNotParseKeyPair
Files are generated using:
openssl req -x509 -nodes -days 365 -newkey rsa:512 -keyout selfsigned.key.pem -out selfsigned-x509.crt -subj "/CN=localhost" -outform PEM
*/
let rcgen_cert_params = rcgen::CertificateParams::from_ca_cert_pem(
&String::from_utf8(crt).unwrap(),
key_pair
).unwrap();
// Use the rcgen cert
let test_certificate = rcgen::Certificate::from_params(rcgen_cert_params).unwrap();
let pem = test_certificate.serialize_pem().unwrap();
let pkey = test_certificate.get_key_pair().serialize_pem();
let identity = native_tls::Identity::from_pkcs8(pem.as_bytes(), pkey.as_bytes()).unwrap();
} |
I think ring does not support RSA-512. The correct creation command is here: https://docs.rs/ring/latest/ring/signature/struct.RsaKeyPair.html#method.from_pkcs8 |
Thanks. Generated a key with: openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | openssl pkcs8 -topk8 -nocrypt -outform pem > private-key.pk8 Generated a Certificate with: openssl req -x509 -nodes -days 365 -key private-key.pk8 -inform pem -out selfsigned-x509.crt -outform pem
-----BEGIN CERTIFICATE-----
MIIDkzCCAnugAwIBAgIUB7bBuVv+3KMN2GTip75hIHUOyEowDQYJKoZIhvcNAQEL
BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X
DTIyMDkxNTA1NTE0NloXDTIzMDkxNTA1NTE0NlowWTELMAkGA1UEBhMCQVUxEzAR
BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAo8qP6dnSOObpO80tkJElPHEA7TjsGeFaBNWRNevGoAGSWO16yYFE
pvPKC96ufkWfJG0qdysle7cali39QsTRFu+8m9YSCU38JVPAL3F5KFt8BNfMiONg
ettRkty5OYlMRd80RcshjkPT8d3T7i1S5IrY7mAwdap2iW6tJKu5Bc2JzugJBI3i
MPLyDwv/iqmADFozm04YL4o0WabxLthfqmJp8iaju9R+/Y5dT6RoXVbL6mbBGUR8
Otl0DuT7iEmjUayb87Ff2fMx7cztx2Zv1SLsa0J+F12MDCWl8WNn6sEs0kzIaS4k
/Bt4h7x2N2IFHBVOghI/uF5ET0GRkjXcGwIDAQABo1MwUTAdBgNVHQ4EFgQUIHaR
a7x7VCTqWnH5sXXcS0g3CX4wHwYDVR0jBBgwFoAUIHaRa7x7VCTqWnH5sXXcS0g3
CX4wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWbOWJWOv+AHA
KW+W6aCu0ZyuOFMTTHTBujH1CshNbN+FzQ47XMI5znTIRMetAq+J5Hsf7CzLpF0+
Mk7okfn0+GxcFMm+ToT0rdetJTy2A0u+7OLIZE+S/sG2cKqT+VbKpzzZiopOz/SZ
YKKvSWXlg8GGaub8Tf1qj7PcTBGGFS9vyMrNx3/kLILT0m1hhlwEpwqo1CAwpn2o
HPfXhAdR5+rA1sVG+30LU+3FhyRiUVwiNJj3l6GnUy3ks9rkzu4oVngu6jGz5BWq
fg8absiPtRcxLXJwSoqy5M2aBAHci30GfhaNIxzFgeBiTubhwhpD6AqB1BBkF68J
cSLkk5VAzQ==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjyo/p2dI45uk7
zS2QkSU8cQDtOOwZ4VoE1ZE168agAZJY7XrJgUSm88oL3q5+RZ8kbSp3KyV7txqW
Lf1CxNEW77yb1hIJTfwlU8AvcXkoW3wE18yI42B621GS3Lk5iUxF3zRFyyGOQ9Px
3dPuLVLkitjuYDB1qnaJbq0kq7kFzYnO6AkEjeIw8vIPC/+KqYAMWjObThgvijRZ
pvEu2F+qYmnyJqO71H79jl1PpGhdVsvqZsEZRHw62XQO5PuISaNRrJvzsV/Z8zHt
zO3HZm/VIuxrQn4XXYwMJaXxY2fqwSzSTMhpLiT8G3iHvHY3YgUcFU6CEj+4XkRP
QZGSNdwbAgMBAAECggEAIf3q6gxTjY2Wf9uwBh2pTabiG1lB3okfJnuwHDGnUhOh
bKU0Y1dZiRB1MQtwyTHnuiaRtpOUvt0cPmii89Vm00zDps/BhH7TwmdkLjRtgYui
7Fpgz1Po9PZJMqJuKlutIZ8V+RoUB7NZ7AsubXKojlemd6osxG6xFQqMEl01E9fk
LQCNi63ur4nOf4HYeuW2mRE+DSQgYmaGNp5CNntymwRt4R54WFj+CJ5QJHWe/U51
Reg2SWMbkZZzgVfa8oEnwpoox6ycip/hifSbt576LXI/Bl+wytGiO2Ua9si/kLOC
dqyNXuy/oPd2bFYGj83Be23FYroPzR5gC4IyIl23aQKBgQDQZCugTux+rcn7Psiq
0e1WYNaVT7WG6lAYDzskCovW2I1eVG9W08pph35KJmtDIqxY2icObpk2IpqiLiDg
qwxIZ3nYjRLKZkF8+XxLLjrceWZcuR3YgIJHRrcTtN0o7IZohQoiUuC4cjsiZ6xn
M2pKLEwj8/YV395eYylW7EFSlwKBgQDJNfHo+mD0IgJ43l+G2Y6kOZ/Um9mp0spB
/SDkctABZ4Yp6M9PCWeamPiqI0LUk9/WRKP6iYQMnhutWRuo+8Rq+YVio6vPy8++
cZx5yZ/JjuMeeBA4wAM1UVSgqAEXdUc5VZ35FXQEjTTD5lh4KMJOvlXT3qkOXKpW
yDI/fmmnHQKBgCoGCUYqpEZnhXPFFXJdIx9oJ920VUb/uWcgqyx5c/m/ccK0BD/e
NdNSH4WUeczwERFZ7MZcR0lDcSuDYd3soG15cHja+g8Wz94D8ay3hecwFBRewEYI
pDz7Za/zqSW3jONG8OQ7ElYfsw0dGwc0txp+FFyrtdRzcMRX+t4shn/BAoGBAJ9S
/ejTSa5Gt9ppiw7GenKDxpGdju8wIEO8Yi1C1H4oMU5CMNWOxuDdvBlMroCRTy7l
T0r1VQCAub27z3ExWsiyJ/KBU2zJIAjXAWZWRxZc9G6N95pYQLIZYn+MSMEAdpNp
vhsb57Aq99sfLHKJI8MiZ+fKaecbbS4me9NXD+XpAoGAFjqGzJIlg11Xx+Umrt03
L4IgMLj1z/7UKW/tfEaUsMQtw4hzdK2jOCs3vN9178LIr0fb8Dd4joWAAD5gyrwZ
BSPT8AjKqyp6KlX5NwHKQrwKa4C7OyBmCmqdS013L07XjNzLmpDEfTUE4tM8DH8f
Xfxr+KAV7sIze+Px67altRk=
-----END PRIVATE KEY-----
Confirmed it still works manually with: use std::fs;
use std::io::Read;
fn main() {
let mut pkey = vec![];
let mut crt = vec![];
fs::File::open("private-key.pk8").unwrap()
.read_to_end(&mut pkey).unwrap();
fs::File::open("selfsigned-x509.crt").unwrap()
.read_to_end(&mut crt).unwrap();
let identity = native_tls::Identity::from_pkcs8(&crt, &pkey).unwrap();
} Trying it with use std::fs;
use std::io::Read;
fn main() {
let mut pkey = vec![];
let mut crt = vec![];
fs::File::open("private-key.pk8").unwrap()
.read_to_end(&mut pkey).unwrap();
fs::File::open("selfsigned-x509.crt").unwrap()
.read_to_end(&mut crt).unwrap();
let key_pair = rcgen::KeyPair::from_pem(
&String::from_utf8(pkey).unwrap()
).unwrap();
let rcgen_cert_params = rcgen::CertificateParams::from_ca_cert_pem(
&String::from_utf8(crt).unwrap(),
key_pair
).unwrap();
// Use the rcgen cert
let test_certificate = rcgen::Certificate::from_params(rcgen_cert_params).unwrap();
let pem = test_certificate.serialize_pem().unwrap();
let pkey = test_certificate.get_key_pair().serialize_pem();
let identity = native_tls::Identity::from_pkcs8(pem.as_bytes(), pkey.as_bytes()).unwrap();
} Does this mean the problem does indeed lie with the generation? |
It might be with the generation, it might be with RSA. If you are still interested, can try generating an P-256 key using the openssl cli utility, and then importing it similar to above. |
I'll give that a go, thanks! |
Is this what you meant? openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -outform pem > private-key.pk8
openssl req -x509 -nodes -days 365 -key private-key.pk8 -inform pem -out selfsigned-x509.crt -outform pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfaWB8eice9MLtw1y
WVy6hlCUvhDIiNd8iiRxxEsr8wuhRANCAARgoS2tqg7inL0V1G/QxUSWGutx4x7r
5vUyNFPNnJ5dn5TbOLk/XAyngKw/1UfLzW+hliHa/Iay8ap5LqGXNXex
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICBjCCAa2gAwIBAgIUEN5ugy4udCDU63hh/kPaEPCG910wCgYIKoZIzj0EAwIw
WTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIy
MDkxNTE3NDIxN1oXDTIzMDkxNTE3NDIxN1owWTELMAkGA1UEBhMCQVUxEzARBgNV
BAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
YKEtraoO4py9FdRv0MVElhrrceMe6+b1MjRTzZyeXZ+U2zi5P1wMp4CsP9VHy81v
oZYh2vyGsvGqeS6hlzV3saNTMFEwHQYDVR0OBBYEFOI0vFSNC2RtKeTNjCvk3odg
OWWVMB8GA1UdIwQYMBaAFOI0vFSNC2RtKeTNjCvk3odgOWWVMA8GA1UdEwEB/wQF
MAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgOkQnY7WbDN2V1EofQ4FK8Apr6/pmwrod
rp2b82PEeqsCIHEHf7RyLZpJbKUkVQV3W/ABB2qV1dWhEaCANeXHdivw
-----END CERTIFICATE-----
And then this actually does raise the use std::fs;
use std::io::Read;
fn main() {
let mut pkey = vec![];
let mut crt = vec![];
fs::File::open("private-key.pk8").unwrap()
.read_to_end(&mut pkey).unwrap();
fs::File::open("selfsigned-x509.crt").unwrap()
.read_to_end(&mut crt).unwrap();
let identity = native_tls::Identity::from_pkcs8(&crt, &pkey).unwrap();
/*
Raises Os { code: -2146881269, kind: Uncategorized, message: "ASN1 bad tag value met." }
With the openssl p-256 key
*/
} Is there a way to configure the generation to get something that will work? |
Oh that's good because then we know that this is because Anyways, this doesn't seem like an rcgen bug to me, but I think this discussion has still been very useful for future readers. I'm closing this. |
reading linked issues, it appears macs / windows expect pkcs8 format to be encrypted? |
It looks like if you explicitly generate the keypair, RSA works on Windows, and is then loadable. The rsa-irc example in this repo does this: params.alg = &rcgen::PKCS_RSA_SHA256;
let mut rng = OsRng;
let bits = 2048;
let private_key = RsaPrivateKey::new(&mut rng, bits)?;
let private_key_der = private_key.to_pkcs8_der()?;
let key_pair = rcgen::KeyPair::try_from(private_key_der.as_bytes()).unwrap();
params.key_pair = Some(key_pair); |
Yeah the issue might be the openssl command. The ring docs have example invocations that generate in the format that ring expects: https://docs.rs/ring/latest/ring/signature/struct.RsaKeyPair.html#method.from_pkcs8 |
Initially thought this issue was related to #82 but that does not seem to be the case.
I need to generate a (very) short-lived
native_tls::TlsStream
for one-shot TLS communication overlocalhost
.Ideally the application can use a temporary
native_tls::Identity
built from a self-signed certificate generated usingrcgen
here's an attempt so far:As indicated, an
ASN1 bad tag value met
is raised by the OS when trying to use the certificate and private key.Any ideas on what is going wrong here?
(This is on Windows 10 and 11)
The text was updated successfully, but these errors were encountered: