aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/x509
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2017-02-11 10:13:00 -0800
committerSteven Fackler <[email protected]>2017-02-11 10:13:00 -0800
commitf2c69ae7e9e9ab6c843c1de842551bb624e7eb2c (patch)
treeb507d4f207a37720d118bb75d86665d2d9a5da2d /openssl/src/x509
parentDocs (diff)
parentMerge pull request #568 from mredlek/x509_req_version_subject (diff)
downloadrust-openssl-f2c69ae7e9e9ab6c843c1de842551bb624e7eb2c.tar.xz
rust-openssl-f2c69ae7e9e9ab6c843c1de842551bb624e7eb2c.zip
Merge remote-tracking branch 'origin/master' into x509-builder
Diffstat (limited to 'openssl/src/x509')
-rw-r--r--openssl/src/x509/mod.rs263
-rw-r--r--openssl/src/x509/store.rs65
-rw-r--r--openssl/src/x509/tests.rs77
3 files changed, 344 insertions, 61 deletions
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
index e3a54d7d..6b65fbd2 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -1,7 +1,8 @@
#![allow(deprecated)]
use libc::{c_int, c_long};
+use ffi;
+use foreign_types::{ForeignType, ForeignTypeRef};
use std::borrow::Borrow;
-use std::cmp;
use std::collections::HashMap;
use std::error::Error;
use std::ffi::{CStr, CString};
@@ -14,17 +15,16 @@ use std::slice;
use std::str;
use {cvt, cvt_p};
-use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef, Asn1IntegerRef};
+use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef, Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef};
+use bio::MemBioSlice;
use bn::{BigNum, MSB_MAYBE_ZERO};
-use bio::{MemBio, MemBioSlice};
use conf::ConfRef;
-use hash::MessageDigest;
-use pkey::{PKey, PKeyRef};
use error::ErrorStack;
-use ffi;
+use hash::MessageDigest;
use nid::{self, Nid};
-use types::{OpenSslType, OpenSslTypeRef};
+use pkey::{PKey, PKeyRef};
use stack::{Stack, StackRef, Stackable};
+use string::OpensslString;
#[cfg(ossl10x)]
use ffi::{X509_set_notBefore, X509_set_notAfter, ASN1_STRING_data, X509_STORE_CTX_get_chain};
@@ -39,6 +39,7 @@ pub mod verify;
use x509::extension::{ExtensionType, Extension};
pub mod extension;
+pub mod store;
#[cfg(test)]
mod tests;
@@ -55,7 +56,13 @@ pub const X509_FILETYPE_PEM: X509FileType = X509FileType(ffi::X509_FILETYPE_PEM)
pub const X509_FILETYPE_ASN1: X509FileType = X509FileType(ffi::X509_FILETYPE_ASN1);
pub const X509_FILETYPE_DEFAULT: X509FileType = X509FileType(ffi::X509_FILETYPE_DEFAULT);
-type_!(X509StoreContext, X509StoreContextRef, ffi::X509_STORE_CTX, ffi::X509_STORE_CTX_free);
+foreign_type! {
+ type CType = ffi::X509_STORE_CTX;
+ fn drop = ffi::X509_STORE_CTX_free;
+
+ pub struct X509StoreContext;
+ pub struct X509StoreContextRef;
+}
impl X509StoreContextRef {
pub fn error(&self) -> Option<X509VerifyError> {
@@ -376,7 +383,13 @@ impl X509Builder {
}
}
-type_!(X509, X509Ref, ffi::X509, ffi::X509_free);
+foreign_type! {
+ type CType = ffi::X509;
+ fn drop = ffi::X509_free;
+
+ pub struct X509;
+ pub struct X509Ref;
+}
impl X509Ref {
pub fn subject_name(&self) -> &X509NameRef {
@@ -420,8 +433,8 @@ impl X509Ref {
}
}
- /// Returns certificate Not After validity period.
- pub fn not_after<'a>(&'a self) -> &'a Asn1TimeRef {
+ /// Returns the certificate's Not After validity period.
+ pub fn not_after(&self) -> &Asn1TimeRef {
unsafe {
let date = compat::X509_get_notAfter(self.as_ptr());
assert!(!date.is_null());
@@ -429,8 +442,8 @@ impl X509Ref {
}
}
- /// Returns certificate Not Before validity period.
- pub fn not_before<'a>(&'a self) -> &'a Asn1TimeRef {
+ /// Returns the certificate's Not Before validity period.
+ pub fn not_before(&self) -> &Asn1TimeRef {
unsafe {
let date = compat::X509_get_notBefore(self.as_ptr());
assert!(!date.is_null());
@@ -438,23 +451,47 @@ impl X509Ref {
}
}
- /// Writes certificate as PEM
- pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
- let mem_bio = try!(MemBio::new());
+ /// Returns the certificate's signature
+ pub fn signature(&self) -> &Asn1BitStringRef {
+ unsafe {
+ let mut signature = ptr::null();
+ compat::X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
+ assert!(!signature.is_null());
+ Asn1BitStringRef::from_ptr(signature as *mut _)
+ }
+ }
+
+ /// Returns the certificate's signature algorithm.
+ pub fn signature_algorithm(&self) -> &X509AlgorithmRef {
+ unsafe {
+ let mut algor = ptr::null();
+ compat::X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
+ assert!(!algor.is_null());
+ X509AlgorithmRef::from_ptr(algor as *mut _)
+ }
+ }
+
+ /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information
+ /// Access field.
+ pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> {
unsafe {
- try!(cvt(ffi::PEM_write_bio_X509(mem_bio.as_ptr(), self.as_ptr())));
+ cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p))
}
- Ok(mem_bio.get_buf().to_owned())
}
- /// Returns a DER serialized form of the certificate
- pub fn to_der(&self) -> Result<Vec<u8>, ErrorStack> {
- let mem_bio = try!(MemBio::new());
+ /// Checks that this certificate issued `subject`.
+ pub fn issued(&self, subject: &X509Ref) -> Result<(), X509VerifyError> {
unsafe {
- ffi::i2d_X509_bio(mem_bio.as_ptr(), self.as_ptr());
+ let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr());
+ match X509VerifyError::from_raw(r as c_long) {
+ Some(e) => Err(e),
+ None => Ok(()),
+ }
}
- Ok(mem_bio.get_buf().to_owned())
}
+
+ to_pem!(ffi::PEM_write_bio_X509);
+ to_der!(ffi::i2d_X509);
}
impl ToOwned for X509Ref {
@@ -474,25 +511,36 @@ impl X509 {
X509Builder::new()
}
- /// Reads a certificate from DER.
- pub fn from_der(buf: &[u8]) -> Result<X509, ErrorStack> {
- unsafe {
- let mut ptr = buf.as_ptr();
- let len = cmp::min(buf.len(), c_long::max_value() as usize) as c_long;
- let x509 = try!(cvt_p(ffi::d2i_X509(ptr::null_mut(), &mut ptr, len)));
- Ok(X509::from_ptr(x509))
- }
- }
+ from_pem!(X509, ffi::PEM_read_bio_X509);
+ from_der!(X509, ffi::d2i_X509);
- /// Reads a certificate from PEM.
- pub fn from_pem(buf: &[u8]) -> Result<X509, ErrorStack> {
- let mem_bio = try!(MemBioSlice::new(buf));
+ /// Deserializes a list of PEM-formatted certificates.
+ pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
unsafe {
- let handle = try!(cvt_p(ffi::PEM_read_bio_X509(mem_bio.as_ptr(),
- ptr::null_mut(),
- None,
- ptr::null_mut())));
- Ok(X509::from_ptr(handle))
+ ffi::init();
+ let bio = try!(MemBioSlice::new(pem));
+
+ let mut certs = vec![];
+ loop {
+ let r = ffi::PEM_read_bio_X509(bio.as_ptr(),
+ ptr::null_mut(),
+ None,
+ ptr::null_mut());
+ if r.is_null() {
+ let err = ffi::ERR_peek_last_error();
+ if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM
+ && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE {
+ ffi::ERR_clear_error();
+ break;
+ }
+
+ return Err(ErrorStack::get());
+ } else {
+ certs.push(X509(r));
+ }
+ }
+
+ Ok(certs)
}
}
}
@@ -534,7 +582,13 @@ impl<'a> X509v3Context<'a> {
}
}
-type_!(X509Extension, X509ExtensionRef, ffi::X509_EXTENSION, ffi::X509_EXTENSION_free);
+foreign_type! {
+ type CType = ffi::X509_EXTENSION;
+ fn drop = ffi::X509_EXTENSION_free;
+
+ pub struct X509Extension;
+ pub struct X509ExtensionRef;
+}
impl Stackable for X509Extension {
type StackType = ffi::stack_st_X509_EXTENSION;
@@ -635,7 +689,13 @@ impl X509NameBuilder {
}
}
-type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free);
+foreign_type! {
+ type CType = ffi::X509_NAME;
+ fn drop = ffi::X509_NAME_free;
+
+ pub struct X509Name;
+ pub struct X509NameRef;
+}
impl X509Name {
/// Returns a new builder.
@@ -694,7 +754,13 @@ impl<'a> Iterator for X509NameEntries<'a> {
}
}
-type_!(X509NameEntry, X509NameEntryRef, ffi::X509_NAME_ENTRY, ffi::X509_NAME_ENTRY_free);
+foreign_type! {
+ type CType = ffi::X509_NAME_ENTRY;
+ fn drop = ffi::X509_NAME_ENTRY_free;
+
+ pub struct X509NameEntry;
+ pub struct X509NameEntryRef;
+}
impl X509NameEntryRef {
pub fn data(&self) -> &Asn1StringRef {
@@ -769,7 +835,13 @@ impl X509ReqBuilder {
}
}
-type_!(X509Req, X509ReqRef, ffi::X509_REQ, ffi::X509_REQ_free);
+foreign_type! {
+ type CType = ffi::X509_REQ;
+ fn drop = ffi::X509_REQ_free;
+
+ pub struct X509Req;
+ pub struct X509ReqRef;
+}
impl X509Req {
pub fn builder() -> Result<X509ReqBuilder, ErrorStack> {
@@ -787,25 +859,40 @@ impl X509Req {
Ok(X509Req::from_ptr(handle))
}
}
+
+ from_der!(X509Req, ffi::d2i_X509_REQ);
}
impl X509ReqRef {
- /// Writes CSR as PEM
- pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
- let mem_bio = try!(MemBio::new());
- if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.as_ptr()) } != 1 {
- return Err(ErrorStack::get());
+ to_pem!(ffi::PEM_write_bio_X509_REQ);
+ to_der!(ffi::i2d_X509_REQ);
+
+ pub fn version(&self) -> i32
+ {
+ unsafe {
+ compat::X509_REQ_get_version(self.as_ptr()) as i32
+ }
+ }
+
+ pub fn set_version(&mut self, value: i32) -> Result<(), ErrorStack>
+ {
+ unsafe {
+ cvt(ffi::X509_REQ_set_version(self.as_ptr(), value as c_long)).map(|_| ())
}
- Ok(mem_bio.get_buf().to_owned())
}
- /// Returns a DER serialized form of the CSR
- pub fn to_der(&self) -> Result<Vec<u8>, ErrorStack> {
- let mem_bio = try!(MemBio::new());
+ pub fn subject_name(&self) -> &X509NameRef {
unsafe {
- ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.as_ptr());
+ let name = compat::X509_REQ_get_subject_name(self.as_ptr());
+ assert!(!name.is_null());
+ X509NameRef::from_ptr(name)
+ }
+ }
+
+ pub fn set_subject_name(&mut self, value: &X509NameRef) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::X509_REQ_set_subject_name(self.as_ptr(), value.as_ptr())).map(|_| ())
}
- Ok(mem_bio.get_buf().to_owned())
}
}
@@ -932,7 +1019,13 @@ impl X509VerifyError {
}
}
-type_!(GeneralName, GeneralNameRef, ffi::GENERAL_NAME, ffi::GENERAL_NAME_free);
+foreign_type! {
+ type CType = ffi::GENERAL_NAME;
+ fn drop = ffi::GENERAL_NAME_free;
+
+ pub struct GeneralName;
+ pub struct GeneralNameRef;
+}
impl GeneralNameRef {
/// Returns the contents of this `GeneralName` if it is a `dNSName`.
@@ -972,18 +1065,42 @@ impl Stackable for GeneralName {
type StackType = ffi::stack_st_GENERAL_NAME;
}
+foreign_type! {
+ type CType = ffi::X509_ALGOR;
+ fn drop = ffi::X509_ALGOR_free;
+
+ pub struct X509Algorithm;
+ pub struct X509AlgorithmRef;
+}
+
+impl X509AlgorithmRef {
+ /// Returns the ASN.1 OID of this algorithm.
+ pub fn object(&self) -> &Asn1ObjectRef {
+ unsafe {
+ let mut oid = ptr::null();
+ compat::X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
+ assert!(!oid.is_null());
+ Asn1ObjectRef::from_ptr(oid as *mut _)
+ }
+ }
+}
+
#[cfg(ossl110)]
mod compat {
pub use ffi::X509_getm_notAfter as X509_get_notAfter;
pub use ffi::X509_getm_notBefore as X509_get_notBefore;
pub use ffi::X509_up_ref;
pub use ffi::X509_get0_extensions;
+ pub use ffi::X509_REQ_get_version;
+ pub use ffi::X509_REQ_get_subject_name;
+ pub use ffi::X509_get0_signature;
+ pub use ffi::X509_ALGOR_get0;
}
#[cfg(ossl10x)]
#[allow(bad_style)]
mod compat {
- use libc::c_int;
+ use libc::{c_int, c_void};
use ffi;
pub unsafe fn X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
@@ -1011,4 +1128,36 @@ mod compat {
(*info).extensions
}
}
+
+ pub unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long
+ {
+ ::ffi::ASN1_INTEGER_get((*(*x).req_info).version)
+ }
+
+ pub unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME
+ {
+ (*(*x).req_info).subject
+ }
+
+ pub unsafe fn X509_get0_signature(psig: *mut *const ffi::ASN1_BIT_STRING,
+ palg: *mut *const ffi::X509_ALGOR,
+ x: *const ffi::X509) {
+ if !psig.is_null() {
+ *psig = (*x).signature;
+ }
+ if !palg.is_null() {
+ *palg = (*x).sig_alg;
+ }
+ }
+
+ pub unsafe fn X509_ALGOR_get0(paobj: *mut *const ffi::ASN1_OBJECT,
+ pptype: *mut c_int,
+ pval: *mut *mut c_void,
+ alg: *const ffi::X509_ALGOR) {
+ if !paobj.is_null() {
+ *paobj = (*alg).algorithm;
+ }
+ assert!(pptype.is_null());
+ assert!(pval.is_null());
+ }
}
diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs
new file mode 100644
index 00000000..8b7a084b
--- /dev/null
+++ b/openssl/src/x509/store.rs
@@ -0,0 +1,65 @@
+use ffi;
+use foreign_types::ForeignTypeRef;
+use std::mem;
+
+use {cvt, cvt_p};
+use error::ErrorStack;
+use x509::X509;
+
+foreign_type! {
+ type CType = ffi::X509_STORE;
+ fn drop = ffi::X509_STORE_free;
+
+ pub struct X509StoreBuilder;
+ pub struct X509StoreBuilderRef;
+}
+
+impl X509StoreBuilder {
+ /// Returns a builder for a certificate store.
+ ///
+ /// The store is initially empty.
+ pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
+ unsafe {
+ ffi::init();
+
+ cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
+ }
+ }
+
+ /// Constructs the `X509Store`.
+ pub fn build(self) -> X509Store {
+ let store = X509Store(self.0);
+ mem::forget(self);
+ store
+ }
+}
+
+impl X509StoreBuilderRef {
+ /// Adds a certificate to the certificate store.
+ pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
+ unsafe {
+ let ptr = cert.as_ptr();
+ mem::forget(cert); // the cert will be freed inside of X509_STORE_add_cert on error
+ cvt(ffi::X509_STORE_add_cert(self.as_ptr(), ptr)).map(|_| ())
+ }
+ }
+
+ /// Load certificates from their default locations.
+ ///
+ /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`
+ /// environment variables if present, or defaults specified at OpenSSL
+ /// build time otherwise.
+ pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ())
+ }
+ }
+}
+
+foreign_type! {
+ type CType = ffi::X509_STORE;
+ fn drop = ffi::X509_STORE_free;
+
+ pub struct X509Store;
+ pub struct X509StoreRef;
+}
diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs
index 514b8edc..2632eade 100644
--- a/openssl/src/x509/tests.rs
+++ b/openssl/src/x509/tests.rs
@@ -1,14 +1,17 @@
-use serialize::hex::FromHex;
+use hex::{FromHex, ToHex};
use asn1::Asn1Time;
use bn::{BigNum, MSB_MAYBE_ZERO};
+use ec::{NAMED_CURVE, EcGroup, EcKey};
use hash::MessageDigest;
+use nid::X9_62_PRIME256V1;
use pkey::PKey;
use rsa::Rsa;
use stack::Stack;
use x509::{X509, X509Generator, X509Name, X509Req};
use x509::extension::{Extension, BasicConstraints, KeyUsage, ExtendedKeyUsage,
SubjectKeyIdentifier, AuthorityKeyIdentifier, SubjectAlternativeName};
+use ssl::{SslMethod, SslContextBuilder};
use x509::extension::AltNameOption as SAN;
use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment};
use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth};
@@ -76,7 +79,12 @@ fn test_req_gen() {
let pkey = pkey();
let req = get_generator().request(&pkey).unwrap();
- req.to_pem().unwrap();
+ let reqpem = req.to_pem().unwrap();
+
+ let req = X509Req::from_pem(&reqpem).ok().expect("Failed to load PEM");
+ let cn = (*req).subject_name().entries_by_nid(nid::COMMONNAME).next().unwrap();
+ assert_eq!(0, (*req).version());
+ assert_eq!(cn.data().as_slice(), b"test_me");
// FIXME: check data in result to be correct, needs implementation
// of X509_REQ getters
@@ -89,7 +97,7 @@ fn test_cert_loading() {
let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap();
let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
- let hash_vec = hash_str.from_hex().unwrap();
+ let hash_vec = Vec::from_hex(hash_str).unwrap();
assert_eq!(fingerprint, hash_vec);
}
@@ -136,7 +144,7 @@ fn test_nid_values() {
assert_eq!(email.data().as_slice(), b"[email protected]");
let friendly = subject.entries_by_nid(nid::FRIENDLYNAME).next().unwrap();
- assert_eq!(&*friendly.data().as_utf8().unwrap(), "Example");
+ assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
}
#[test]
@@ -260,3 +268,64 @@ fn x509_req_builder() {
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
}
+
+#[test]
+fn test_stack_from_pem() {
+ let certs = include_bytes!("../../test/certs.pem");
+ let certs = X509::stack_from_pem(certs).unwrap();
+
+ assert_eq!(certs.len(), 2);
+ assert_eq!(certs[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
+ "59172d9313e84459bcff27f967e79e6e9217e584");
+ assert_eq!(certs[1].fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
+ "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875");
+}
+
+#[test]
+fn issued() {
+ 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();
+
+ ca.issued(&cert).unwrap();
+ cert.issued(&cert).err().unwrap();
+}
+
+#[test]
+fn ecdsa_cert() {
+ let mut group = EcGroup::from_curve_name(X9_62_PRIME256V1).unwrap();
+ group.set_asn1_flag(NAMED_CURVE);
+ let key = EcKey::generate(&group).unwrap();
+ let key = PKey::from_ec_key(key).unwrap();
+
+ let cert = X509Generator::new()
+ .set_valid_period(365)
+ .add_name("CN".to_owned(), "TestServer".to_owned())
+ .set_sign_hash(MessageDigest::sha256())
+ .sign(&key)
+ .unwrap();
+
+ let mut ctx = SslContextBuilder::new(SslMethod::tls()).unwrap();
+ ctx.set_certificate(&cert).unwrap();
+ ctx.set_private_key(&key).unwrap();
+ ctx.check_private_key().unwrap();
+}
+
+#[test]
+fn signature() {
+ let cert = include_bytes!("../../test/cert.pem");
+ let cert = X509::from_pem(cert).unwrap();
+ let signature = cert.signature();
+ assert_eq!(signature.as_slice().to_hex(),
+ "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
+ 78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
+ 4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
+ ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
+ 89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
+ f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
+ e121997410d37c");
+ let algorithm = cert.signature_algorithm();
+ assert_eq!(algorithm.object().nid(), nid::SHA256WITHRSAENCRYPTION);
+ assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption");
+}