Loading openssl-sys/src/handwritten/x509_vfy.rs +14 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,12 @@ extern "C" { pub fn X509_STORE_set_flags(store: *mut X509_STORE, flags: c_ulong) -> c_int; } const_ptr_api! { extern "C" { pub fn X509_STORE_set1_param(store: *mut X509_STORE, pm: #[const_ptr_if(ossl300)] X509_VERIFY_PARAM) -> c_int; } } const_ptr_api! { extern "C" { pub fn X509_STORE_CTX_get_ex_data(ctx: #[const_ptr_if(ossl300)] X509_STORE_CTX, idx: c_int) -> *mut c_void; Loading @@ -73,6 +79,8 @@ cfg_if! { } extern "C" { #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_new() -> *mut X509_VERIFY_PARAM; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM); Loading @@ -80,6 +88,12 @@ extern "C" { pub fn X509_VERIFY_PARAM_set_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_clear_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_set_time(param: *mut X509_VERIFY_PARAM, t: time_t); #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_set_depth(param: *mut X509_VERIFY_PARAM, depth: c_int); } const_ptr_api! { extern "C" { Loading openssl/src/x509/store.rs +8 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ use crate::error::ErrorStack; use crate::ssl::SslFiletype; use crate::stack::StackRef; #[cfg(any(ossl102, libressl261))] use crate::x509::verify::X509VerifyFlags; use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef}; use crate::x509::{X509Object, X509}; use crate::{cvt, cvt_p}; use openssl_macros::corresponds; Loading Loading @@ -122,6 +122,13 @@ impl X509StoreBuilderRef { pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) } } /// Sets certificate chain validation related parameters. #[corresponds[X509_STORE_set1_param]] #[cfg(any(ossl102, libressl261))] pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) } } } generic_foreign_type_and_impl_send_sync! { Loading openssl/src/x509/tests.rs +126 −1 Original line number Diff line number Diff line Loading @@ -13,11 +13,13 @@ use crate::x509::extension::{ }; use crate::x509::store::X509StoreBuilder; #[cfg(any(ossl102, libressl261))] use crate::x509::verify::X509VerifyFlags; use crate::x509::verify::{X509VerifyFlags, X509VerifyParam}; #[cfg(ossl110)] use crate::x509::X509Builder; use crate::x509::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509}; use hex::{self, FromHex}; #[cfg(any(ossl102, libressl261))] use libc::time_t; fn pkey() -> PKey<Private> { let rsa = Rsa::generate(2048).unwrap(); Loading Loading @@ -543,3 +545,126 @@ fn test_name_cmp() { assert_eq!(Ordering::Equal, subject.try_cmp(subject).unwrap()); assert_eq!(Ordering::Greater, subject.try_cmp(issuer).unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_time_fails_verification() { const TEST_T_2030: time_t = 1893456000; let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); verify_params.set_time(TEST_T_2030); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert_eq!( context .init(&store, &cert, &chain, |c| { c.verify_cert()?; Ok(c.error()) }) .unwrap() .error_string(), "certificate has expired" ) } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_time() { const TEST_T_2020: time_t = 1577836800; let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); verify_params.set_time(TEST_T_2020); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context .init(&store, &cert, &chain, |c| c.verify_cert()) .unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_depth() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let mut chain = Stack::new().unwrap(); chain.push(intermediate_ca).unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do let expected_depth = if cfg!(any(ossl110)) { 1 } else { 2 }; verify_params.set_depth(expected_depth); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context .init(&store, &cert, &chain, |c| c.verify_cert()) .unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_depth_fails_verification() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let mut chain = Stack::new().unwrap(); chain.push(intermediate_ca).unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do let expected_depth = if cfg!(any(ossl110)) { 0 } else { 1 }; verify_params.set_depth(expected_depth); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); // OpenSSL 1.1.0+ added support for X509_V_ERR_CERT_CHAIN_TOO_LONG, while 1.0.2 simply ignores the intermediate let expected_error = if cfg!(any(ossl110, libressl261)) { "certificate chain too long" } else { "unable to get local issuer certificate" }; let mut context = X509StoreContext::new().unwrap(); assert_eq!( context .init(&store, &cert, &chain, |c| { c.verify_cert()?; Ok(c.error()) }) .unwrap() .error_string(), expected_error ) } openssl/src/x509/verify.rs +25 −2 Original line number Diff line number Diff line use bitflags::bitflags; use foreign_types::ForeignTypeRef; use libc::{c_uint, c_ulong}; use libc::{c_int, c_uint, c_ulong, time_t}; use std::net::IpAddr; use crate::cvt; use crate::error::ErrorStack; use crate::{cvt, cvt_p}; use openssl_macros::corresponds; bitflags! { Loading Loading @@ -69,6 +69,17 @@ foreign_type_and_impl_send_sync! { pub struct X509VerifyParamRef; } impl X509VerifyParam { /// Create an X509VerifyParam #[corresponds(X509_VERIFY_PARAM_new)] pub fn new() -> Result<X509VerifyParam, ErrorStack> { unsafe { ffi::init(); cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam) } } } impl X509VerifyParamRef { /// Set the host flags. #[corresponds(X509_VERIFY_PARAM_set_hostflags)] Loading Loading @@ -139,4 +150,16 @@ impl X509VerifyParamRef { .map(|_| ()) } } /// Set the verification time, where time is of type time_t, traditionaly defined as seconds since the epoch #[corresponds(X509_VERIFY_PARAM_set_time)] pub fn set_time(&mut self, time: time_t) { unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) } } /// Set the verification depth #[corresponds(X509_VERIFY_PARAM_set_depth)] pub fn set_depth(&mut self, depth: c_int) { unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) } } } openssl/test/intermediate-ca.key 0 → 100644 +27 −0 Original line number Diff line number Diff line -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA1HsHFTpgKeWL/y6oKtARZm0Dy6J/08E0CujmdpVp0xnkXi/A RARnbMEbOPfmBUMOkVtQT3+l5aCgIAX+Kg6K7sQvio8nQUgOxuO1YpGlYu9EMtc7 5fNxA1T0CuXXx8ClfEqW1ZV7ziQV0J4gzvuI26A7XyUhdk1oP/Al3F/94TmH6dtP SQ2K901O2zknU+bpPheQy08SE20k/nUOJAsiwtsxqY8hHOL1sXZ4K+I311hl0QpD OYf7eBcBdo2Mc5Nzjd9LPGLk1lE3itAXpayFMmfuuA0IdH1gNfy18axFEEVnj6CS 2epGpmAckUEWUOse1WBhDEt6ddowT1iw7X4mWwIDAQABAoIBAGMGXzuudAiymTc5 OFiTlbhlkAJEXkyC201GU7nqUmJ2y651lKZeYxEVQimfpszG/rARnXEfbWKCJH4o LNbO5kL2na12n/XVrkVU9EDW3fwoxGDpXFoDxaSm4AGAMrs+diFh5b/upb9ho+UQ /PtZ0OOCXokuFdU7qB08P3jgJ8LhooqWnZ4AC0rhN85CMNIKs/nrUrnmS3FZLVd/ NWI9Vfjsndd41Gkho0A7tgOSnwRupk/Bv1b0px31h8ucp9/nLuR8vbGSdS/R9Sta pB9KNYYQ3LrhQGjddnEU0gj8qsuWgnoPf7eaWsLVunPLHQzL2hNNKL1eBADm7Lhh avIlnrkCgYEA8Q8UhOeIO0sMU8sB4NPTUf2UT9xjURoowGsGgbDEk21eABH6VC33 VYt5r5xwbZFQvVaTbe+EI1YDpjH1cvpmorEWI47Nm4Vbf9JujW/hoQwuwpzOpdUT 2G4tfMQrmTw/9HJ0l9+1Ib+A93dB8GvR0NE1uueaWanWvXARInwGiscCgYEA4aZ9 mbhuwx88sSRMXwxSZw+R5BRrjdC0CeoimGg4/P84bKgc0YsjAha5jWaC/h8xN2Pb w45b3hQ0/FP8xohP0bp/5eeiDbqb6JuO5bI3CnfBrVpu1CAuIrf7lhkar3a0wluB k03fVHuVLtydACDJBKrZm1F39lpiZiEqlBIp080CgYEAwRwYjwPAEefkHzhQ7+Ah uNwQtQ1TjsQLA2J5mumWAJirphjA1jDgo+oQ+Iq1UkEIUjWJ85bd30TntXruK0bH c+uzVZbvxXfGvhZAtBN9x/svdn4R2a1hsY9J51prpt0qStRp7MSsoTV9xkEGVOi6 87K1fV5OOyggvC+Lunlq8D8CgYAVSCOObPOdWYPa3SaKzFm1OKW00iw2qtlgGgH7 R9EgI14J+W0GYk4B82y6plFycDSvGa7vaazGbDd3GOC9RLvqduF7KHaDPvdXX9yB U2aXiSXuGJpdTU+snJeQ13tJ0zNHJWQ6JV0L1cADNHFmQrFSzF5LpMpgpLOlGDmw z2m8fQKBgQDclFeonyn0zcXqznun9kAKkMij4s6lSdRgi/5Zh1WbJwOso9oWfwz9 SSTP2KBO8B+/yFvuo5SWrbNaTz9/KuzMTv4HXz5ukLbyN9Jjtk73fdBBRSjL+zF5 jU56oXHrwBhEqWQ77Ps60r+FmDjUgUhyJl14ZfkzICUK7NLFxKrvMQ== -----END RSA PRIVATE KEY----- Loading
openssl-sys/src/handwritten/x509_vfy.rs +14 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,12 @@ extern "C" { pub fn X509_STORE_set_flags(store: *mut X509_STORE, flags: c_ulong) -> c_int; } const_ptr_api! { extern "C" { pub fn X509_STORE_set1_param(store: *mut X509_STORE, pm: #[const_ptr_if(ossl300)] X509_VERIFY_PARAM) -> c_int; } } const_ptr_api! { extern "C" { pub fn X509_STORE_CTX_get_ex_data(ctx: #[const_ptr_if(ossl300)] X509_STORE_CTX, idx: c_int) -> *mut c_void; Loading @@ -73,6 +79,8 @@ cfg_if! { } extern "C" { #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_new() -> *mut X509_VERIFY_PARAM; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM); Loading @@ -80,6 +88,12 @@ extern "C" { pub fn X509_VERIFY_PARAM_set_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_clear_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int; #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_set_time(param: *mut X509_VERIFY_PARAM, t: time_t); #[cfg(any(ossl102, libressl261))] pub fn X509_VERIFY_PARAM_set_depth(param: *mut X509_VERIFY_PARAM, depth: c_int); } const_ptr_api! { extern "C" { Loading
openssl/src/x509/store.rs +8 −1 Original line number Diff line number Diff line Loading @@ -50,7 +50,7 @@ use crate::error::ErrorStack; use crate::ssl::SslFiletype; use crate::stack::StackRef; #[cfg(any(ossl102, libressl261))] use crate::x509::verify::X509VerifyFlags; use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef}; use crate::x509::{X509Object, X509}; use crate::{cvt, cvt_p}; use openssl_macros::corresponds; Loading Loading @@ -122,6 +122,13 @@ impl X509StoreBuilderRef { pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) } } /// Sets certificate chain validation related parameters. #[corresponds[X509_STORE_set1_param]] #[cfg(any(ossl102, libressl261))] pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) } } } generic_foreign_type_and_impl_send_sync! { Loading
openssl/src/x509/tests.rs +126 −1 Original line number Diff line number Diff line Loading @@ -13,11 +13,13 @@ use crate::x509::extension::{ }; use crate::x509::store::X509StoreBuilder; #[cfg(any(ossl102, libressl261))] use crate::x509::verify::X509VerifyFlags; use crate::x509::verify::{X509VerifyFlags, X509VerifyParam}; #[cfg(ossl110)] use crate::x509::X509Builder; use crate::x509::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509}; use hex::{self, FromHex}; #[cfg(any(ossl102, libressl261))] use libc::time_t; fn pkey() -> PKey<Private> { let rsa = Rsa::generate(2048).unwrap(); Loading Loading @@ -543,3 +545,126 @@ fn test_name_cmp() { assert_eq!(Ordering::Equal, subject.try_cmp(subject).unwrap()); assert_eq!(Ordering::Greater, subject.try_cmp(issuer).unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_time_fails_verification() { const TEST_T_2030: time_t = 1893456000; let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); verify_params.set_time(TEST_T_2030); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert_eq!( context .init(&store, &cert, &chain, |c| { c.verify_cert()?; Ok(c.error()) }) .unwrap() .error_string(), "certificate has expired" ) } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_time() { const TEST_T_2020: time_t = 1577836800; let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); verify_params.set_time(TEST_T_2020); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context .init(&store, &cert, &chain, |c| c.verify_cert()) .unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_depth() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let mut chain = Stack::new().unwrap(); chain.push(intermediate_ca).unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do let expected_depth = if cfg!(any(ossl110)) { 1 } else { 2 }; verify_params.set_depth(expected_depth); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context .init(&store, &cert, &chain, |c| c.verify_cert()) .unwrap()); } #[test] #[cfg(any(ossl102, libressl261))] fn test_verify_param_set_depth_fails_verification() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem"); let intermediate_ca = X509::from_pem(intermediate_ca).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let mut chain = Stack::new().unwrap(); chain.push(intermediate_ca).unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let mut verify_params = X509VerifyParam::new().unwrap(); // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do let expected_depth = if cfg!(any(ossl110)) { 0 } else { 1 }; verify_params.set_depth(expected_depth); store_bldr.set_param(&verify_params).unwrap(); let store = store_bldr.build(); // OpenSSL 1.1.0+ added support for X509_V_ERR_CERT_CHAIN_TOO_LONG, while 1.0.2 simply ignores the intermediate let expected_error = if cfg!(any(ossl110, libressl261)) { "certificate chain too long" } else { "unable to get local issuer certificate" }; let mut context = X509StoreContext::new().unwrap(); assert_eq!( context .init(&store, &cert, &chain, |c| { c.verify_cert()?; Ok(c.error()) }) .unwrap() .error_string(), expected_error ) }
openssl/src/x509/verify.rs +25 −2 Original line number Diff line number Diff line use bitflags::bitflags; use foreign_types::ForeignTypeRef; use libc::{c_uint, c_ulong}; use libc::{c_int, c_uint, c_ulong, time_t}; use std::net::IpAddr; use crate::cvt; use crate::error::ErrorStack; use crate::{cvt, cvt_p}; use openssl_macros::corresponds; bitflags! { Loading Loading @@ -69,6 +69,17 @@ foreign_type_and_impl_send_sync! { pub struct X509VerifyParamRef; } impl X509VerifyParam { /// Create an X509VerifyParam #[corresponds(X509_VERIFY_PARAM_new)] pub fn new() -> Result<X509VerifyParam, ErrorStack> { unsafe { ffi::init(); cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam) } } } impl X509VerifyParamRef { /// Set the host flags. #[corresponds(X509_VERIFY_PARAM_set_hostflags)] Loading Loading @@ -139,4 +150,16 @@ impl X509VerifyParamRef { .map(|_| ()) } } /// Set the verification time, where time is of type time_t, traditionaly defined as seconds since the epoch #[corresponds(X509_VERIFY_PARAM_set_time)] pub fn set_time(&mut self, time: time_t) { unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) } } /// Set the verification depth #[corresponds(X509_VERIFY_PARAM_set_depth)] pub fn set_depth(&mut self, depth: c_int) { unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) } } }
openssl/test/intermediate-ca.key 0 → 100644 +27 −0 Original line number Diff line number Diff line -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA1HsHFTpgKeWL/y6oKtARZm0Dy6J/08E0CujmdpVp0xnkXi/A RARnbMEbOPfmBUMOkVtQT3+l5aCgIAX+Kg6K7sQvio8nQUgOxuO1YpGlYu9EMtc7 5fNxA1T0CuXXx8ClfEqW1ZV7ziQV0J4gzvuI26A7XyUhdk1oP/Al3F/94TmH6dtP SQ2K901O2zknU+bpPheQy08SE20k/nUOJAsiwtsxqY8hHOL1sXZ4K+I311hl0QpD OYf7eBcBdo2Mc5Nzjd9LPGLk1lE3itAXpayFMmfuuA0IdH1gNfy18axFEEVnj6CS 2epGpmAckUEWUOse1WBhDEt6ddowT1iw7X4mWwIDAQABAoIBAGMGXzuudAiymTc5 OFiTlbhlkAJEXkyC201GU7nqUmJ2y651lKZeYxEVQimfpszG/rARnXEfbWKCJH4o LNbO5kL2na12n/XVrkVU9EDW3fwoxGDpXFoDxaSm4AGAMrs+diFh5b/upb9ho+UQ /PtZ0OOCXokuFdU7qB08P3jgJ8LhooqWnZ4AC0rhN85CMNIKs/nrUrnmS3FZLVd/ NWI9Vfjsndd41Gkho0A7tgOSnwRupk/Bv1b0px31h8ucp9/nLuR8vbGSdS/R9Sta pB9KNYYQ3LrhQGjddnEU0gj8qsuWgnoPf7eaWsLVunPLHQzL2hNNKL1eBADm7Lhh avIlnrkCgYEA8Q8UhOeIO0sMU8sB4NPTUf2UT9xjURoowGsGgbDEk21eABH6VC33 VYt5r5xwbZFQvVaTbe+EI1YDpjH1cvpmorEWI47Nm4Vbf9JujW/hoQwuwpzOpdUT 2G4tfMQrmTw/9HJ0l9+1Ib+A93dB8GvR0NE1uueaWanWvXARInwGiscCgYEA4aZ9 mbhuwx88sSRMXwxSZw+R5BRrjdC0CeoimGg4/P84bKgc0YsjAha5jWaC/h8xN2Pb w45b3hQ0/FP8xohP0bp/5eeiDbqb6JuO5bI3CnfBrVpu1CAuIrf7lhkar3a0wluB k03fVHuVLtydACDJBKrZm1F39lpiZiEqlBIp080CgYEAwRwYjwPAEefkHzhQ7+Ah uNwQtQ1TjsQLA2J5mumWAJirphjA1jDgo+oQ+Iq1UkEIUjWJ85bd30TntXruK0bH c+uzVZbvxXfGvhZAtBN9x/svdn4R2a1hsY9J51prpt0qStRp7MSsoTV9xkEGVOi6 87K1fV5OOyggvC+Lunlq8D8CgYAVSCOObPOdWYPa3SaKzFm1OKW00iw2qtlgGgH7 R9EgI14J+W0GYk4B82y6plFycDSvGa7vaazGbDd3GOC9RLvqduF7KHaDPvdXX9yB U2aXiSXuGJpdTU+snJeQ13tJ0zNHJWQ6JV0L1cADNHFmQrFSzF5LpMpgpLOlGDmw z2m8fQKBgQDclFeonyn0zcXqznun9kAKkMij4s6lSdRgi/5Zh1WbJwOso9oWfwz9 SSTP2KBO8B+/yFvuo5SWrbNaTz9/KuzMTv4HXz5ukLbyN9Jjtk73fdBBRSjL+zF5 jU56oXHrwBhEqWQ77Ps60r+FmDjUgUhyJl14ZfkzICUK7NLFxKrvMQ== -----END RSA PRIVATE KEY-----