Last active
September 26, 2023 14:20
-
-
Save stofte/fb338b847533b762f25d91e4e8db976f to your computer and use it in GitHub Desktop.
rustc 1.72.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "rust-cert" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
windows-sys = { version = "0.48", features = [ | |
"Win32_Foundation", | |
"Win32_Security_Cryptography"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ffi::{c_void, OsStr}; | |
use std::os::windows::ffi::OsStrExt; | |
use std::ptr::null_mut; | |
use std::io::Write; | |
use std::fs; | |
use windows_sys::{ | |
w, | |
Win32::Security::Cryptography::{ | |
CertCloseStore, CertFindCertificateInStore, CertOpenStore, CryptStringToBinaryW, | |
CertAddCertificateContextToStore, CertFreeCertificateContext, PFXExportCertStoreEx, | |
CERT_CLOSE_STORE_CHECK_FLAG, CERT_FIND_HASH, CERT_OPEN_STORE_FLAGS, | |
CERT_QUERY_ENCODING_TYPE, CERT_STORE_PROV_MEMORY, CERT_STORE_PROV_SYSTEM_W, | |
CERT_SYSTEM_STORE_CURRENT_USER_ID, CERT_SYSTEM_STORE_LOCATION_SHIFT, CRYPT_INTEGER_BLOB, | |
CRYPT_STRING_HEXRAW, HCRYPTPROV_LEGACY, PKCS_7_ASN_ENCODING, X509_ASN_ENCODING, | |
CERT_CONTEXT, CERT_STORE_ADD_USE_EXISTING, EXPORT_PRIVATE_KEYS, | |
REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY, | |
}, | |
}; | |
fn main() { | |
unsafe { | |
let memory_store = CertOpenStore( | |
CERT_STORE_PROV_MEMORY, | |
CERT_QUERY_ENCODING_TYPE::default(), | |
HCRYPTPROV_LEGACY::default(), | |
CERT_OPEN_STORE_FLAGS::default(), | |
std::ptr::null(), | |
); | |
let store_name = OsStr::new("My") | |
.encode_wide() | |
.chain(Some(0)) | |
.collect::<Vec<_>>(); | |
let user_store = CertOpenStore( | |
CERT_STORE_PROV_SYSTEM_W, | |
CERT_QUERY_ENCODING_TYPE::default(), | |
HCRYPTPROV_LEGACY::default(), | |
CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT, | |
store_name.as_ptr() as *const c_void, | |
); | |
if user_store.is_null() { | |
println!("user_store is null!"); | |
} else { | |
println!("user_store obtained!"); | |
} | |
let cert_thumbprint = w!("72f26338e9a4aefa3d54fe2ab66aaf85ce711805"); | |
let hash_vec = vec![0; 40]; | |
let mut hash_blob = CRYPT_INTEGER_BLOB { | |
cbData: 40 as u32, | |
pbData: hash_vec.as_ptr() as _, | |
}; | |
if CryptStringToBinaryW( | |
cert_thumbprint, | |
hash_blob.cbData, | |
CRYPT_STRING_HEXRAW, | |
hash_blob.pbData, | |
&mut hash_blob.cbData, | |
null_mut(), | |
null_mut(), | |
) == 0 | |
{ | |
println!("Failed to write hash thumbprint"); | |
} | |
let foo_ptr: *const c_void = &hash_blob as *const _ as _; | |
let cert_context = CertFindCertificateInStore( | |
user_store, | |
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, | |
0, | |
CERT_FIND_HASH, | |
foo_ptr, | |
std::ptr::null_mut(), | |
); | |
if cert_context.is_null() { | |
println!("No certificate was found!"); | |
} else { | |
println!("Certificate was found!"); | |
} | |
let foob: *const CERT_CONTEXT = cert_context; | |
if CertAddCertificateContextToStore(memory_store, foob, CERT_STORE_ADD_USE_EXISTING, null_mut()) == 1 { | |
println!("Added cert to memory store"); | |
} else { | |
println!("Failed to add cert to memory store"); | |
} | |
if CertFreeCertificateContext(foob) == 0 { | |
println!("Failed to free certificate context"); | |
} | |
if CertCloseStore(user_store, CERT_CLOSE_STORE_CHECK_FLAG) == 1 { | |
println!("Closed user_store"); | |
} else { | |
println!("Could NOT close user_store (due to unfreed resources)"); | |
} | |
let mut pfx_blob = CRYPT_INTEGER_BLOB { | |
cbData: 0, | |
pbData: null_mut(), | |
}; | |
if PFXExportCertStoreEx( | |
memory_store, | |
&mut pfx_blob, | |
null_mut(), | |
null_mut(), | |
EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | |
) == 1 { | |
println!("PFX required size: {}", pfx_blob.cbData); | |
let pfx_vec: Vec<u8> = vec![0; pfx_blob.cbData as usize]; | |
pfx_blob.pbData = pfx_vec.as_ptr() as _; | |
if PFXExportCertStoreEx( | |
memory_store, | |
&mut pfx_blob, | |
null_mut(), | |
null_mut(), | |
EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | |
) == 1 { | |
println!("PFX export success"); | |
fs::write("rust-cert.pfx", pfx_vec).unwrap(); | |
} else { | |
println!("PFX export failed"); | |
} | |
} | |
if CertCloseStore(memory_store, CERT_CLOSE_STORE_CHECK_FLAG) == 1 { | |
println!("Closed memory_store"); | |
} else { | |
println!("Could NOT close memory_store (due to unfreed resources)"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment