Browse Source

Correction of KeyPair, PublicKey, adding PrivateKey

Hovsep Papoyan 6 months ago
parent
commit
275aa07813

+ 3 - 0
build.rs

@@ -6,6 +6,7 @@ fn main()
         .file("src/KeyPair.cc")
         .file("src/Params.cc")
         .file("src/Plaintext.cc")
+        .file("src/PrivateKey.cc")
         .file("src/PublicKey.cc")
         .file("src/SerialDeserial.cc")
         .file("src/EvalKey.cc")
@@ -38,6 +39,8 @@ fn main()
     println!("cargo::rerun-if-changed=src/Params.cc");
     println!("cargo::rerun-if-changed=src/Plaintext.h");
     println!("cargo::rerun-if-changed=src/Plaintext.cc");
+    println!("cargo::rerun-if-changed=src/PrivateKey.h");
+    println!("cargo::rerun-if-changed=src/PrivateKey.cc");
     println!("cargo::rerun-if-changed=src/PublicKey.h");
     println!("cargo::rerun-if-changed=src/PublicKey.cc");
     println!("cargo::rerun-if-changed=src/SerialDeserial.h");

+ 6 - 6
examples/function_evaluation.rs

@@ -26,7 +26,7 @@ fn EvalLogisticExample()
     _cc.Enable(ffi::PKESchemeFeature::ADVANCEDSHE);
 
     let _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+    _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
 
     let mut _input = CxxVector::<ffi::ComplexPair>::new();
     _input.pin_mut().push(ffi::ComplexPair{re: -4.0, im: 0.0});
@@ -40,13 +40,13 @@ fn EvalLogisticExample()
     _input.pin_mut().push(ffi::ComplexPair{re: 4.0, im: 0.0});
     let _encoded_length: usize = _input.len();
     let _plain_text = _cc.MakeCKKSPackedPlaintextByVectorOfComplex(&_input, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
-    let _cipher_text = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text);
+    let _cipher_text = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text);
     let _lower_bound: f64 = -5.0;
     let _upper_bound: f64 = 5.0;
     let _result = _cc.EvalLogistic(&_cipher_text, _lower_bound, _upper_bound, _poly_degree);
 
     let mut _plain_text_dec = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
     _plain_text_dec.SetLength(_encoded_length);
 
     let mut _expected_output = CxxVector::<ffi::ComplexPair>::new();
@@ -94,7 +94,7 @@ fn EvalFunctionExample()
     _cc.Enable(ffi::PKESchemeFeature::ADVANCEDSHE);
 
     let _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+    _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
     let mut _input = CxxVector::<ffi::ComplexPair>::new();
     _input.pin_mut().push(ffi::ComplexPair{re: 1.0, im: 0.0});
     _input.pin_mut().push(ffi::ComplexPair{re: 2.0, im: 0.0});
@@ -108,13 +108,13 @@ fn EvalFunctionExample()
 
     let _encoded_length: usize = _input.len();
     let _plain_text = _cc.MakeCKKSPackedPlaintextByVectorOfComplex(&_input, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
-    let _cipher_text = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text);
+    let _cipher_text = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text);
     let _lower_bound: f64 = 0.0;
     let _upper_bound: f64 = 10.0;
     let _result = _cc.EvalChebyshevFunction(GetSqrt, &_cipher_text, _lower_bound, _upper_bound, _poly_degree);
 
     let mut _plain_text_dec = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
     _plain_text_dec.SetLength(_encoded_length);
 
     let mut _expected_output = CxxVector::<ffi::ComplexPair>::new();

+ 4 - 4
examples/polynomial_evaluation.rs

@@ -78,9 +78,9 @@ fn main()
     let _plain_text_1 = _cc.MakeCKKSPackedPlaintextByVectorOfComplex(&_input, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
     let _key_pair = _cc.KeyGen();
     print!("Generating evaluation key for homomorphic multiplication...");
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+    _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
     println!("Completed.\n");
-    let mut _cipher_text_1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_1);
+    let mut _cipher_text_1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_1);
 
     let mut _start = Instant::now();
     let _result = _cc.EvalPoly(&_cipher_text_1, &_coefficients_1);
@@ -91,10 +91,10 @@ fn main()
     let _time_eval_poly_2 = _start.elapsed();
 
     let mut _plain_text_dec = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
     _plain_text_dec.SetLength(_encoded_length);
     let mut _plain_text_dec_2 = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result_2, _plain_text_dec_2.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result_2, _plain_text_dec_2.pin_mut());
     _plain_text_dec_2.SetLength(_encoded_length);
 
     println!("\n Original Plaintext #1:");

+ 12 - 12
examples/simple_integers.rs

@@ -1,4 +1,4 @@
-use openfhe::cxx::{CxxVector, SharedPtr};
+use openfhe::cxx::{CxxVector};
 use openfhe::ffi as ffi;
 
 fn main()
@@ -13,14 +13,14 @@ fn main()
     _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
 
     let _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+    _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
 
     let mut _index_list = CxxVector::<i32>::new();
     _index_list.pin_mut().push(1);
     _index_list.pin_mut().push(2);
     _index_list.pin_mut().push(-1);
     _index_list.pin_mut().push(-2);
-    _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
+    _cc.EvalRotateKeyGen(&_key_pair.GetPrivateKey(), &_index_list, &ffi::GenNullPublicKey());
 
     let mut _vector_of_ints_1 = CxxVector::<i64>::new();
     _vector_of_ints_1.pin_mut().push(1);
@@ -67,9 +67,9 @@ fn main()
     _vector_of_ints_3.pin_mut().push(12);
     let _plain_text_3 = _cc.MakePackedPlaintext(&_vector_of_ints_3, 1, 0);
 
-    let _cipher_text_1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_1);
-    let _cipher_text_2 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_2);
-    let _cipher_text_3 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_3);
+    let _cipher_text_1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_1);
+    let _cipher_text_2 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_2);
+    let _cipher_text_3 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_3);
 
     let _cipher_text_add_1_2 = _cc.EvalAddByCiphertexts(&_cipher_text_1, &_cipher_text_2);
     let _cipher_text_add_result = _cc.EvalAddByCiphertexts(&_cipher_text_add_1_2, &_cipher_text_3);
@@ -83,17 +83,17 @@ fn main()
     let _cipher_text_rot_4 = _cc.EvalRotate(&_cipher_text_1, -2);
 
     let mut _plain_text_add_result = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_add_result, _plain_text_add_result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_add_result, _plain_text_add_result.pin_mut());
     let mut _plain_text_mult_result = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_mult_result, _plain_text_mult_result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_mult_result, _plain_text_mult_result.pin_mut());
     let mut _plain_text_rot_1 = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_1, _plain_text_rot_1.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_1, _plain_text_rot_1.pin_mut());
     let mut _plain_text_rot_2 = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_2, _plain_text_rot_2.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_2, _plain_text_rot_2.pin_mut());
     let mut _plain_text_rot_3 = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_3, _plain_text_rot_3.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_3, _plain_text_rot_3.pin_mut());
     let mut _plain_text_rot_4 = ffi::GenEmptyPlainText();
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_4, _plain_text_rot_4.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_4, _plain_text_rot_4.pin_mut());
 
     _plain_text_rot_1.SetLength(_vector_of_ints_1.len());
     _plain_text_rot_2.SetLength(_vector_of_ints_1.len());

+ 11 - 11
examples/simple_real_numbers.rs

@@ -20,11 +20,11 @@ fn main()
     println!("CKKS scheme is using ring dimension {}\n", _cc.GetRingDimension());
 
     let _key_pair = _cc.KeyGen();
-    _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+    _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
     let mut _index_list = CxxVector::<i32>::new();
     _index_list.pin_mut().push(1);
     _index_list.pin_mut().push(-2);
-    _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
+    _cc.EvalRotateKeyGen(&_key_pair.GetPrivateKey(), &_index_list, &ffi::GenNullPublicKey());
 
     let mut _x_1 = CxxVector::<f64>::new();
     _x_1.pin_mut().push(0.25);
@@ -52,8 +52,8 @@ fn main()
     println!("Input x1: {}", _p_txt_1.GetString());
     println!("Input x2: {}", _p_txt_2.GetString());
 
-    let _c1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_p_txt_1);
-    let _c2 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_p_txt_2);
+    let _c1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_p_txt_1);
+    let _c2 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_p_txt_2);
 
     let _c_add = _cc.EvalAddByCiphertexts(&_c1, &_c2);
     let _c_sub = _cc.EvalSubByCiphertexts(&_c1, &_c2);
@@ -65,32 +65,32 @@ fn main()
     let mut _result = ffi::GenEmptyPlainText();
     println!("\nResults of homomorphic computations:");
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c1, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c1, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("x1 = {}Estimated precision in bits: {}", _result.GetString(), _result.GetLogPrecision());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_add, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_add, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("x1 + x2 = {}Estimated precision in bits: {}",_result.GetString(), _result.GetLogPrecision());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_sub, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_sub, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("x1 - x2 = {}", _result.GetString());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_scalar, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_scalar, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("4 * x1 = {}", _result.GetString());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_mul, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_mul, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("x1 * x2 = {}", _result.GetString());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_rot_1, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_rot_1, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("\nIn rotations, very small outputs (~10^-10 here) correspond to 0's:");
     println!("x1 rotate by 1 = {}", _result.GetString());
 
-    _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_rot_2, _result.pin_mut());
+    _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_rot_2, _result.pin_mut());
     _result.SetLength(_batch_size.try_into().unwrap());
     println!("x1 rotate by -2 = {}", _result.GetString());
 }

+ 53 - 53
src/CryptoContext.cc

@@ -10,6 +10,7 @@
 #include "Ciphertext.h"
 #include "KeyPair.h"
 #include "Plaintext.h"
+#include "PrivateKey.h"
 #include "PublicKey.h"
 #include "EvalKey.h"
 #include "LWEPrivateKey.h"
@@ -104,23 +105,25 @@ std::unique_ptr<KeyPairDCRTPoly> CryptoContextDCRTPoly::SparseKeyGen() const
 {
     return std::make_unique<KeyPairDCRTPoly>(m_cryptoContextImplSharedPtr->SparseKeyGen());
 }
-void CryptoContextDCRTPoly::EvalMultKeyGen(const std::shared_ptr<PrivateKeyImpl> key) const
+void CryptoContextDCRTPoly::EvalMultKeyGen(const PrivateKeyDCRTPoly& key) const
 {
-    m_cryptoContextImplSharedPtr->EvalMultKeyGen(key);
+    m_cryptoContextImplSharedPtr->EvalMultKeyGen(key.GetInternal());
 }
-void CryptoContextDCRTPoly::EvalMultKeysGen(const std::shared_ptr<PrivateKeyImpl> key) const
+void CryptoContextDCRTPoly::EvalMultKeysGen(const PrivateKeyDCRTPoly& key) const
 {
-    m_cryptoContextImplSharedPtr->EvalMultKeysGen(key);
+    m_cryptoContextImplSharedPtr->EvalMultKeysGen(key.GetInternal());
 }
-void CryptoContextDCRTPoly::EvalRotateKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
-    const std::vector<int32_t>& indexList, const std::shared_ptr<PublicKeyImpl> publicKey) const
+void CryptoContextDCRTPoly::EvalRotateKeyGen(const PrivateKeyDCRTPoly& privateKey,
+    const std::vector<int32_t>& indexList, const PublicKeyDCRTPoly& publicKey) const
 {
-    m_cryptoContextImplSharedPtr->EvalRotateKeyGen(privateKey, indexList, publicKey);
+    m_cryptoContextImplSharedPtr->EvalRotateKeyGen(privateKey.GetInternal(), indexList,
+    publicKey.GetInternal());
 }
-void CryptoContextDCRTPoly::EvalAtIndexKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
-    const std::vector<int32_t>& indexList, const std::shared_ptr<PublicKeyImpl> publicKey) const
+void CryptoContextDCRTPoly::EvalAtIndexKeyGen(const PrivateKeyDCRTPoly& privateKey,
+    const std::vector<int32_t>& indexList, const PublicKeyDCRTPoly& publicKey) const
 {
-    m_cryptoContextImplSharedPtr->EvalAtIndexKeyGen(privateKey, indexList, publicKey);
+    m_cryptoContextImplSharedPtr->EvalAtIndexKeyGen(privateKey.GetInternal(), indexList,
+    publicKey.GetInternal());
 }
 void CryptoContextDCRTPoly::EvalCKKStoFHEWPrecompute(const double scale) const
 {
@@ -144,16 +147,16 @@ std::unique_ptr<Plaintext> CryptoContextDCRTPoly::MakeCoefPackedPlaintext(
         noiseScaleDeg, level));
 }
 std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EncryptByPublicKey(
-    const std::shared_ptr<PublicKeyImpl> publicKey, const Plaintext& plaintext) const
+    const PublicKeyDCRTPoly& publicKey, const Plaintext& plaintext) const
 {
-    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(publicKey,
-        plaintext.GetInternal()));
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(
+        publicKey.GetInternal(), plaintext.GetInternal()));
 }
 std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EncryptByPrivateKey(
-    const std::shared_ptr<PrivateKeyImpl> privateKey, const Plaintext& plaintext) const
+    const PrivateKeyDCRTPoly& privateKey, const Plaintext& plaintext) const
 {
-    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(privateKey,
-        plaintext.GetInternal()));
+    return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->Encrypt(
+        privateKey.GetInternal(), plaintext.GetInternal()));
 }
 std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::EvalAddByCiphertexts(
     const CiphertextDCRTPoly& ciphertext1, const CiphertextDCRTPoly& ciphertext2) const
@@ -524,32 +527,34 @@ void CryptoContextDCRTPoly::EvalBootstrapSetup(
     m_cryptoContextImplSharedPtr->EvalBootstrapSetup(levelBudget, dim1, slots, correctionFactor,
         precompute);
 }
-void CryptoContextDCRTPoly::EvalBootstrapKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
+void CryptoContextDCRTPoly::EvalBootstrapKeyGen(const PrivateKeyDCRTPoly& privateKey,
     const uint32_t slots) const
 {
-    m_cryptoContextImplSharedPtr->EvalBootstrapKeyGen(privateKey, slots);
+    m_cryptoContextImplSharedPtr->EvalBootstrapKeyGen(privateKey.GetInternal(), slots);
 }
 void CryptoContextDCRTPoly::EvalBootstrapPrecompute(const uint32_t slots) const
 {
     m_cryptoContextImplSharedPtr->EvalBootstrapPrecompute(slots);
 }
 std::unique_ptr<DecryptResult> CryptoContextDCRTPoly::DecryptByPrivateKeyAndCiphertext(
-    const std::shared_ptr<PrivateKeyImpl> privateKey, const CiphertextDCRTPoly& ciphertext,
+    const PrivateKeyDCRTPoly& privateKey, const CiphertextDCRTPoly& ciphertext,
     Plaintext& plaintext) const
 {
     std::shared_ptr<PlaintextImpl> res;
     std::unique_ptr<DecryptResult> result = std::make_unique<DecryptResult>(
-    m_cryptoContextImplSharedPtr->Decrypt(privateKey, ciphertext.GetInternal(), &res));
+    m_cryptoContextImplSharedPtr->Decrypt(privateKey.GetInternal(), ciphertext.GetInternal(),
+    &res));
     plaintext = res;
     return result;
 }
 std::unique_ptr<DecryptResult> CryptoContextDCRTPoly::DecryptByCiphertextAndPrivateKey(
-    const CiphertextDCRTPoly& ciphertext, const std::shared_ptr<PrivateKeyImpl> privateKey,
+    const CiphertextDCRTPoly& ciphertext, const PrivateKeyDCRTPoly& privateKey,
     Plaintext& plaintext) const
 {
     std::shared_ptr<PlaintextImpl> res;
     std::unique_ptr<DecryptResult> result = std::make_unique<DecryptResult>(
-    m_cryptoContextImplSharedPtr->Decrypt(ciphertext.GetInternal(), privateKey, &res));
+    m_cryptoContextImplSharedPtr->Decrypt(ciphertext.GetInternal(), privateKey.GetInternal(),
+    &res));
     plaintext = res;
     return result;
 }
@@ -706,32 +711,29 @@ void CryptoContextDCRTPoly::LevelReduceInPlace(const CiphertextDCRTPoly& ciphert
 }
 std::unique_ptr<CiphertextDCRTPoly> CryptoContextDCRTPoly::ReEncrypt(
     const CiphertextDCRTPoly& ciphertext, const EvalKeyDCRTPoly& evalKey,
-    const std::shared_ptr<PublicKeyImpl> publicKey) const
+    const PublicKeyDCRTPoly& publicKey) const
 {
     return std::make_unique<CiphertextDCRTPoly>(m_cryptoContextImplSharedPtr->ReEncrypt(
-        ciphertext.GetInternal(), evalKey.GetInternal(), publicKey));
+        ciphertext.GetInternal(), evalKey.GetInternal(), publicKey.GetInternal()));
 }
-
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::KeySwitchGen(
-    const std::shared_ptr<PrivateKeyImpl> oldPrivateKey,
-    const std::shared_ptr<PrivateKeyImpl> newPrivateKey) const
+    const PrivateKeyDCRTPoly& oldPrivateKey, const PrivateKeyDCRTPoly& newPrivateKey) const
 {
     return std::make_unique<EvalKeyDCRTPoly>(m_cryptoContextImplSharedPtr->KeySwitchGen(
-        oldPrivateKey, newPrivateKey));
+        oldPrivateKey.GetInternal(), newPrivateKey.GetInternal()));
 }
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::ReKeyGen(
-    const std::shared_ptr<PrivateKeyImpl> oldPrivateKey,
-    const std::shared_ptr<PublicKeyImpl> newPublicKey) const
+    const PrivateKeyDCRTPoly& oldPrivateKey, const PublicKeyDCRTPoly& newPublicKey) const
 {
     return std::make_unique<EvalKeyDCRTPoly>(m_cryptoContextImplSharedPtr->ReKeyGen(
-        oldPrivateKey, newPublicKey));
+        oldPrivateKey.GetInternal(), newPublicKey.GetInternal()));
 }
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiKeySwitchGen(
-    const std::shared_ptr<PrivateKeyImpl> originalPrivateKey,
-    const std::shared_ptr<PrivateKeyImpl> newPrivateKey, const EvalKeyDCRTPoly& evalKey) const
+    const PrivateKeyDCRTPoly& originalPrivateKey, const PrivateKeyDCRTPoly& newPrivateKey,
+    const EvalKeyDCRTPoly& evalKey) const
 {
     return std::make_unique<EvalKeyDCRTPoly>(m_cryptoContextImplSharedPtr->MultiKeySwitchGen(
-        originalPrivateKey, newPrivateKey, evalKey.GetInternal()));
+        originalPrivateKey.GetInternal(), newPrivateKey.GetInternal(), evalKey.GetInternal()));
 }
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiAddEvalKeys(
     const EvalKeyDCRTPoly& evalKey1, const EvalKeyDCRTPoly& evalKey2,
@@ -741,11 +743,11 @@ std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiAddEvalKeys(
         evalKey1.GetInternal(), evalKey2.GetInternal(), keyId));
 }
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiMultEvalKey(
-    const std::shared_ptr<PrivateKeyImpl> privateKey, const EvalKeyDCRTPoly& evalKey,
+    const PrivateKeyDCRTPoly& privateKey, const EvalKeyDCRTPoly& evalKey,
     const std::string& keyId) const
 {
     return std::make_unique<EvalKeyDCRTPoly>(m_cryptoContextImplSharedPtr->MultiMultEvalKey(
-        privateKey, evalKey.GetInternal(), keyId));
+        privateKey.GetInternal(), evalKey.GetInternal(), keyId));
 }
 std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiAddEvalMultKeys(
     const EvalKeyDCRTPoly& evalKey1, const EvalKeyDCRTPoly& evalKey2,
@@ -754,29 +756,29 @@ std::unique_ptr<EvalKeyDCRTPoly> CryptoContextDCRTPoly::MultiAddEvalMultKeys(
     return std::make_unique<EvalKeyDCRTPoly>(m_cryptoContextImplSharedPtr->MultiAddEvalMultKeys(
         evalKey1.GetInternal(), evalKey2.GetInternal(), keyId));
 }
-void CryptoContextDCRTPoly::EvalSumKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
-    const std::shared_ptr<PublicKeyImpl> publicKey) const
+void CryptoContextDCRTPoly::EvalSumKeyGen(const PrivateKeyDCRTPoly& privateKey,
+    const PublicKeyDCRTPoly& publicKey) const
 {
-    m_cryptoContextImplSharedPtr->EvalSumKeyGen(privateKey, publicKey);
+    m_cryptoContextImplSharedPtr->EvalSumKeyGen(privateKey.GetInternal(), publicKey.GetInternal());
 }
 void CryptoContextDCRTPoly::EvalCKKStoFHEWKeyGen(const KeyPairDCRTPoly& keyPair,
     const LWEPrivateKey& lwesk) const
 {
-    m_cryptoContextImplSharedPtr->EvalCKKStoFHEWKeyGen({keyPair.GetPublicKey(),
-        keyPair.GetPrivateKey()}, lwesk.GetInternal());
+    m_cryptoContextImplSharedPtr->EvalCKKStoFHEWKeyGen({keyPair.GetPublicKey()->GetInternal(),
+        keyPair.GetPrivateKey()->GetInternal()}, lwesk.GetInternal());
 }
 void CryptoContextDCRTPoly::EvalFHEWtoCKKSKeyGen(const KeyPairDCRTPoly& keyPair,
     const LWEPrivateKey& lwesk, const uint32_t numSlots, const uint32_t numCtxts,
     const uint32_t dim1, const uint32_t L) const
 {
-    m_cryptoContextImplSharedPtr->EvalFHEWtoCKKSKeyGen({keyPair.GetPublicKey(),
-        keyPair.GetPrivateKey()}, lwesk.GetInternal(), numSlots, numCtxts, dim1, L);
+    m_cryptoContextImplSharedPtr->EvalFHEWtoCKKSKeyGen({keyPair.GetPublicKey()->GetInternal(),
+        keyPair.GetPrivateKey()->GetInternal()}, lwesk.GetInternal(), numSlots, numCtxts, dim1, L);
 }
 void CryptoContextDCRTPoly::EvalSchemeSwitchingKeyGen(const KeyPairDCRTPoly& keyPair,
     const LWEPrivateKey& lwesk) const
 {
-    m_cryptoContextImplSharedPtr->EvalSchemeSwitchingKeyGen({keyPair.GetPublicKey(),
-        keyPair.GetPrivateKey()}, lwesk.GetInternal());
+    m_cryptoContextImplSharedPtr->EvalSchemeSwitchingKeyGen({keyPair.GetPublicKey()->GetInternal(),
+        keyPair.GetPrivateKey()->GetInternal()}, lwesk.GetInternal());
 }
 uint64_t CryptoContextDCRTPoly::GetModulus() const
 {
@@ -787,27 +789,25 @@ uint64_t CryptoContextDCRTPoly::GetRootOfUnity() const
     return m_cryptoContextImplSharedPtr->GetRootOfUnity().ConvertToInt();
 }
 std::unique_ptr<VectorOfCiphertexts> CryptoContextDCRTPoly::MultipartyDecryptLead(
-    const VectorOfCiphertexts& ciphertextVec,
-    const std::shared_ptr<PrivateKeyImpl> privateKey) const
+    const VectorOfCiphertexts& ciphertextVec, const PrivateKeyDCRTPoly& privateKey) const
 {
     return std::make_unique<VectorOfCiphertexts>(
         m_cryptoContextImplSharedPtr->MultipartyDecryptLead(ciphertextVec.GetInternal(),
-        privateKey));
+        privateKey.GetInternal()));
 }
 std::unique_ptr<VectorOfCiphertexts> CryptoContextDCRTPoly::MultipartyDecryptMain(
-    const VectorOfCiphertexts& ciphertextVec,
-    const std::shared_ptr<PrivateKeyImpl> privateKey) const
+    const VectorOfCiphertexts& ciphertextVec, const PrivateKeyDCRTPoly& privateKey) const
 {
     return std::make_unique<VectorOfCiphertexts>(
         m_cryptoContextImplSharedPtr->MultipartyDecryptMain(ciphertextVec.GetInternal(),
-        privateKey));
+        privateKey.GetInternal()));
 }
 std::unique_ptr<VectorOfCiphertexts> CryptoContextDCRTPoly::IntMPBootDecrypt(
-    const std::shared_ptr<PrivateKeyImpl> privateKey, const CiphertextDCRTPoly& ciphertext,
+    const PrivateKeyDCRTPoly& privateKey, const CiphertextDCRTPoly& ciphertext,
     const CiphertextDCRTPoly& a) const
 {
     return std::make_unique<VectorOfCiphertexts>(m_cryptoContextImplSharedPtr->IntMPBootDecrypt(
-        privateKey, ciphertext.GetInternal(), a.GetInternal()));
+        privateKey.GetInternal(), ciphertext.GetInternal(), a.GetInternal()));
 }
 std::unique_ptr<VectorOfCiphertexts> CryptoContextDCRTPoly::EvalMinSchemeSwitching(
     const CiphertextDCRTPoly& ciphertext, const PublicKeyDCRTPoly& publicKey,

+ 24 - 28
src/CryptoContext.h

@@ -30,6 +30,7 @@ namespace openfhe
 struct ComplexPair;
 
 class KeyPairDCRTPoly;
+class PrivateKeyDCRTPoly;
 class PublicKeyDCRTPoly;
 class Plaintext;
 class CiphertextDCRTPoly;
@@ -94,14 +95,14 @@ public:
         const PublicKeyDCRTPoly& publicKey1, const PublicKeyDCRTPoly& publicKey2,
         const std::string& keyId /* "" */) const;
     [[nodiscard]] std::unique_ptr<KeyPairDCRTPoly> SparseKeyGen() const;
-    void EvalMultKeyGen(const std::shared_ptr<PrivateKeyImpl> key) const;
-    void EvalMultKeysGen(const std::shared_ptr<PrivateKeyImpl> key) const;
-    void EvalRotateKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
+    void EvalMultKeyGen(const PrivateKeyDCRTPoly& key) const;
+    void EvalMultKeysGen(const PrivateKeyDCRTPoly& key) const;
+    void EvalRotateKeyGen(const PrivateKeyDCRTPoly& privateKey,
         const std::vector<int32_t>& indexList,
-        const std::shared_ptr<PublicKeyImpl> publicKey /* nullptr */) const;
-    void EvalAtIndexKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
+        const PublicKeyDCRTPoly& publicKey /* GenNullPublicKey() */) const;
+    void EvalAtIndexKeyGen(const PrivateKeyDCRTPoly& privateKey,
         const std::vector<int32_t>& indexList,
-        const std::shared_ptr<PublicKeyImpl> publicKey /* nullptr */) const;
+        const PublicKeyDCRTPoly& publicKey /* GenNullPublicKey() */) const;
     void EvalCKKStoFHEWPrecompute(const double scale /* 1.0 */) const;
     [[nodiscard]] uint32_t GetRingDimension() const;
     [[nodiscard]] uint32_t GetCyclotomicOrder() const;
@@ -110,9 +111,9 @@ public:
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalCos(const CiphertextDCRTPoly& ciphertext,
         const double a, const double b, const uint32_t degree) const;
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EncryptByPublicKey(
-        const std::shared_ptr<PublicKeyImpl> publicKey, const Plaintext& plaintext) const;
+        const PublicKeyDCRTPoly& publicKey, const Plaintext& plaintext) const;
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EncryptByPrivateKey(
-        const std::shared_ptr<PrivateKeyImpl> privateKey, const Plaintext& plaintext) const;
+        const PrivateKeyDCRTPoly& privateKey, const Plaintext& plaintext) const;
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalAddByCiphertexts(
         const CiphertextDCRTPoly& ciphertext1, const CiphertextDCRTPoly& ciphertext2) const;
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> EvalAddByCiphertextAndPlaintext(
@@ -261,14 +262,13 @@ public:
     void EvalBootstrapSetup(const std::vector<uint32_t>& levelBudget /* {5, 4} */,
         const std::vector<uint32_t>& dim1 /* {0, 0} */, const uint32_t slots /* 0 */,
         const uint32_t correctionFactor /* 0 */, const bool precompute /* true */) const;
-    void EvalBootstrapKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
-        const uint32_t slots) const;
+    void EvalBootstrapKeyGen(const PrivateKeyDCRTPoly& privateKey, const uint32_t slots) const;
     void EvalBootstrapPrecompute(const uint32_t slots /* 0 */) const;
     [[nodiscard]] std::unique_ptr<DecryptResult> DecryptByPrivateKeyAndCiphertext(
-        const std::shared_ptr<PrivateKeyImpl> privateKey, const CiphertextDCRTPoly& ciphertext,
+        const PrivateKeyDCRTPoly& privateKey, const CiphertextDCRTPoly& ciphertext,
         Plaintext& plaintext) const;
     [[nodiscard]] std::unique_ptr<DecryptResult> DecryptByCiphertextAndPrivateKey(
-        const CiphertextDCRTPoly& ciphertext, const std::shared_ptr<PrivateKeyImpl> privateKey,
+        const CiphertextDCRTPoly& ciphertext, const PrivateKeyDCRTPoly& privateKey,
         Plaintext& plaintext) const;
     [[nodiscard]] std::unique_ptr<Plaintext> MakePackedPlaintext(
         const std::vector<int64_t>& value, const size_t noiseScaleDeg /* 1 */,
@@ -304,27 +304,25 @@ public:
         const size_t levels /* 1 */) const;
     [[nodiscard]] std::unique_ptr<CiphertextDCRTPoly> ReEncrypt(
         const CiphertextDCRTPoly& ciphertext, const EvalKeyDCRTPoly& evalKey,
-        const std::shared_ptr<PublicKeyImpl> publicKey /* nullptr */) const;
+        const PublicKeyDCRTPoly& publicKey /* GenNullPublicKey() */) const;
     [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> KeySwitchGen(
-        const std::shared_ptr<PrivateKeyImpl> oldPrivateKey,
-        const std::shared_ptr<PrivateKeyImpl> newPrivateKey) const;
-    [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> ReKeyGen(
-        const std::shared_ptr<PrivateKeyImpl> oldPrivateKey,
-        const std::shared_ptr<PublicKeyImpl> newPublicKey) const;
+        const PrivateKeyDCRTPoly& oldPrivateKey, const PrivateKeyDCRTPoly& newPrivateKey) const;
+    [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> ReKeyGen(const PrivateKeyDCRTPoly& oldPrivateKey,
+        const PublicKeyDCRTPoly& newPublicKey) const;
     [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> MultiKeySwitchGen(
-        const std::shared_ptr<PrivateKeyImpl> originalPrivateKey,
-        const std::shared_ptr<PrivateKeyImpl> newPrivateKey, const EvalKeyDCRTPoly& evalKey) const;
+        const PrivateKeyDCRTPoly& originalPrivateKey, const PrivateKeyDCRTPoly& newPrivateKey,
+        const EvalKeyDCRTPoly& evalKey) const;
     [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> MultiAddEvalKeys(
         const EvalKeyDCRTPoly& evalKey1, const EvalKeyDCRTPoly& evalKey2,
         const std::string& keyId /* "" */) const;
     [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> MultiMultEvalKey(
-        const std::shared_ptr<PrivateKeyImpl> privateKey, const EvalKeyDCRTPoly& evalKey,
+        const PrivateKeyDCRTPoly& privateKey, const EvalKeyDCRTPoly& evalKey,
         const std::string& keyId /* "" */) const;
     [[nodiscard]] std::unique_ptr<EvalKeyDCRTPoly> MultiAddEvalMultKeys(
         const EvalKeyDCRTPoly& evalKey1, const EvalKeyDCRTPoly& evalKey2,
         const std::string& keyId /* "" */) const;
-    void EvalSumKeyGen(const std::shared_ptr<PrivateKeyImpl> privateKey,
-        const std::shared_ptr<PublicKeyImpl> publicKey /* nullptr */) const;
+    void EvalSumKeyGen(const PrivateKeyDCRTPoly& privateKey,
+        const PublicKeyDCRTPoly& publicKey /* GenNullPublicKey() */) const;
     void EvalCKKStoFHEWKeyGen(const KeyPairDCRTPoly& keyPair, const LWEPrivateKey& lwesk) const;
     void EvalFHEWtoCKKSKeyGen(const KeyPairDCRTPoly& keyPair, const LWEPrivateKey& lwesk,
         const uint32_t numSlots /* 0 */, const uint32_t numCtxts /* 0 */,
@@ -334,13 +332,11 @@ public:
     [[nodiscard]] uint64_t GetModulus() const;
     [[nodiscard]] uint64_t GetRootOfUnity() const;
     [[nodiscard]] std::unique_ptr<VectorOfCiphertexts> MultipartyDecryptLead(
-        const VectorOfCiphertexts& ciphertextVec,
-        const std::shared_ptr<PrivateKeyImpl> privateKey) const;
+        const VectorOfCiphertexts& ciphertextVec, const PrivateKeyDCRTPoly& privateKey) const;
     [[nodiscard]] std::unique_ptr<VectorOfCiphertexts> MultipartyDecryptMain(
-        const VectorOfCiphertexts& ciphertextVec,
-        const std::shared_ptr<PrivateKeyImpl> privateKey) const;
+        const VectorOfCiphertexts& ciphertextVec, const PrivateKeyDCRTPoly& privateKey) const;
     [[nodiscard]] std::unique_ptr<VectorOfCiphertexts> IntMPBootDecrypt(
-        const std::shared_ptr<PrivateKeyImpl> privateKey, const CiphertextDCRTPoly& ciphertext,
+        const PrivateKeyDCRTPoly& privateKey, const CiphertextDCRTPoly& ciphertext,
         const CiphertextDCRTPoly& a) const;
     [[nodiscard]] std::unique_ptr<VectorOfCiphertexts> EvalMinSchemeSwitching(
         const CiphertextDCRTPoly& ciphertext, const PublicKeyDCRTPoly& publicKey,

+ 7 - 4
src/KeyPair.cc

@@ -2,6 +2,9 @@
 
 #include "openfhe/pke/key/keypair.h"
 
+#include "PublicKey.h"
+#include "PrivateKey.h"
+
 namespace openfhe
 {
 
@@ -9,13 +12,13 @@ KeyPairDCRTPoly::KeyPairDCRTPoly(const KeyPair& keyPair)
     : m_publicKey(keyPair.publicKey)
     , m_privateKey(keyPair.secretKey)
 { }
-std::shared_ptr<PublicKeyImpl> KeyPairDCRTPoly::GetPublicKey() const
+std::unique_ptr<PublicKeyDCRTPoly> KeyPairDCRTPoly::GetPublicKey() const
 {
-    return m_publicKey;
+    return std::make_unique<PublicKeyDCRTPoly>(m_publicKey);
 }
-std::shared_ptr<PrivateKeyImpl> KeyPairDCRTPoly::GetPrivateKey() const
+std::unique_ptr<PrivateKeyDCRTPoly> KeyPairDCRTPoly::GetPrivateKey() const
 {
-    return m_privateKey;
+    return std::make_unique<PrivateKeyDCRTPoly>(m_privateKey);
 }
 
 } // openfhe

+ 5 - 2
src/KeyPair.h

@@ -15,6 +15,9 @@ class KeyPair;
 namespace openfhe
 {
 
+class PublicKeyDCRTPoly;
+class PrivateKeyDCRTPoly;
+
 using PublicKeyImpl = lbcrypto::PublicKeyImpl<lbcrypto::DCRTPoly>;
 using PrivateKeyImpl = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>;
 using KeyPair = lbcrypto::KeyPair<lbcrypto::DCRTPoly>;
@@ -30,8 +33,8 @@ public:
     KeyPairDCRTPoly& operator=(const KeyPairDCRTPoly&) = delete;
     KeyPairDCRTPoly& operator=(KeyPairDCRTPoly&&) = delete;
 
-    [[nodiscard]] std::shared_ptr<PublicKeyImpl> GetPublicKey() const;
-    [[nodiscard]] std::shared_ptr<PrivateKeyImpl> GetPrivateKey() const;
+    [[nodiscard]] std::unique_ptr<PublicKeyDCRTPoly> GetPublicKey() const;
+    [[nodiscard]] std::unique_ptr<PrivateKeyDCRTPoly> GetPrivateKey() const;
 };
 
 } // openfhe

+ 19 - 0
src/PrivateKey.cc

@@ -0,0 +1,19 @@
+#include "PrivateKey.h"
+
+#include "openfhe/pke/key/privatekey.h"
+
+namespace openfhe
+{
+
+PrivateKeyDCRTPoly::PrivateKeyDCRTPoly()
+    : m_privateKey(std::make_shared<PrivateKeyImpl>())
+{ }
+PrivateKeyDCRTPoly::PrivateKeyDCRTPoly(const std::shared_ptr<PrivateKeyImpl>& privateKey)
+    : m_privateKey(privateKey)
+{ }
+std::shared_ptr<PrivateKeyImpl> PrivateKeyDCRTPoly::GetInternal() const
+{
+    return m_privateKey;
+}
+
+} // openfhe

+ 25 - 0
src/PrivateKey.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "openfhe/core/lattice/hal/lat-backend.h"
+#include "openfhe/pke/key/privatekey-fwd.h"
+
+namespace openfhe
+{
+
+using PrivateKeyImpl = lbcrypto::PrivateKeyImpl<lbcrypto::DCRTPoly>;
+
+class PrivateKeyDCRTPoly final
+{
+    std::shared_ptr<PrivateKeyImpl> m_privateKey;
+public:
+    explicit PrivateKeyDCRTPoly();
+    explicit PrivateKeyDCRTPoly(const std::shared_ptr<PrivateKeyImpl>& privateKey);
+    PrivateKeyDCRTPoly(const PrivateKeyDCRTPoly&) = delete;
+    PrivateKeyDCRTPoly(PrivateKeyDCRTPoly&&) = delete;
+    PrivateKeyDCRTPoly& operator=(const PrivateKeyDCRTPoly&) = delete;
+    PrivateKeyDCRTPoly& operator=(PrivateKeyDCRTPoly&&) = delete;
+
+    [[nodiscard]] std::shared_ptr<PrivateKeyImpl> GetInternal() const;
+};
+
+} // openfhe

+ 7 - 0
src/PublicKey.cc

@@ -8,6 +8,9 @@ namespace openfhe
 PublicKeyDCRTPoly::PublicKeyDCRTPoly()
     : m_publicKey(std::make_shared<PublicKeyImpl>())
 { }
+PublicKeyDCRTPoly::PublicKeyDCRTPoly(const std::nullptr_t)
+    : m_publicKey(nullptr)
+{ }
 PublicKeyDCRTPoly::PublicKeyDCRTPoly(const std::shared_ptr<PublicKeyImpl>& publicKey)
     : m_publicKey(publicKey)
 { }
@@ -19,5 +22,9 @@ std::unique_ptr<PublicKeyDCRTPoly> GenDefaultConstructedPublicKey()
 {
     return std::make_unique<PublicKeyDCRTPoly>();
 }
+std::unique_ptr<PublicKeyDCRTPoly> GenNullPublicKey()
+{
+    return std::make_unique<PublicKeyDCRTPoly>(nullptr);
+}
 
 } // openfhe

+ 3 - 0
src/PublicKey.h

@@ -20,7 +20,9 @@ public:
         PublicKeyDCRTPoly& publicKey, const SerialMode serialMode);
 
     explicit PublicKeyDCRTPoly();
+    explicit PublicKeyDCRTPoly(const std::nullptr_t);
     explicit PublicKeyDCRTPoly(const std::shared_ptr<PublicKeyImpl>& publicKey);
+
     PublicKeyDCRTPoly(const PublicKeyDCRTPoly&) = delete;
     PublicKeyDCRTPoly(PublicKeyDCRTPoly&&) = delete;
     PublicKeyDCRTPoly& operator=(const PublicKeyDCRTPoly&) = delete;
@@ -29,5 +31,6 @@ public:
     [[nodiscard]] std::shared_ptr<PublicKeyImpl> GetInternal() const;
 };
 [[nodiscard]] std::unique_ptr<PublicKeyDCRTPoly> GenDefaultConstructedPublicKey();
+[[nodiscard]] std::unique_ptr<PublicKeyDCRTPoly> GenNullPublicKey();
 
 } // openfhe

+ 56 - 52
src/lib.rs

@@ -151,6 +151,7 @@ pub mod ffi
         include!("openfhe/src/KeyPair.h");
         include!("openfhe/src/Params.h");
         include!("openfhe/src/Plaintext.h");
+        include!("openfhe/src/PrivateKey.h");
         include!("openfhe/src/PublicKey.h");
         include!("openfhe/src/SerialDeserial.h");
         include!("openfhe/src/EvalKey.h");
@@ -184,6 +185,7 @@ pub mod ffi
         type ParamsCKKSRNS;
         type Plaintext;
         type PrivateKeyImpl;
+        type PrivateKeyDCRTPoly;
         type PublicKeyDCRTPoly;
         type PublicKeyImpl;
         type EvalKeyDCRTPoly;
@@ -485,13 +487,14 @@ pub mod ffi
     unsafe extern "C++"
     {
         fn GenDefaultConstructedPublicKey() -> UniquePtr<PublicKeyDCRTPoly>;
+        fn GenNullPublicKey() -> UniquePtr<PublicKeyDCRTPoly>;
     }
 
     // KeyPairDCRTPoly
     unsafe extern "C++"
     {
-        fn GetPrivateKey(self: &KeyPairDCRTPoly) -> SharedPtr<PrivateKeyImpl>;
-        fn GetPublicKey(self: &KeyPairDCRTPoly) -> SharedPtr<PublicKeyImpl>;
+        fn GetPrivateKey(self: &KeyPairDCRTPoly) -> UniquePtr<PrivateKeyDCRTPoly>;
+        fn GetPublicKey(self: &KeyPairDCRTPoly) -> UniquePtr<PublicKeyDCRTPoly>;
     }
 
     // Plaintext
@@ -552,21 +555,21 @@ pub mod ffi
         fn MultiAddPubKeys(self: &CryptoContextDCRTPoly, publicKey1: &PublicKeyDCRTPoly,
                            publicKey2: &PublicKeyDCRTPoly, keyId: /* "" */ &CxxString)
                            -> UniquePtr<PublicKeyDCRTPoly>;
-        fn EvalMultKeyGen(self: &CryptoContextDCRTPoly, key: SharedPtr<PrivateKeyImpl>);
-        fn EvalMultKeysGen(self: &CryptoContextDCRTPoly, key: SharedPtr<PrivateKeyImpl>);
-        fn EvalRotateKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+        fn EvalMultKeyGen(self: &CryptoContextDCRTPoly, key: &PrivateKeyDCRTPoly);
+        fn EvalMultKeysGen(self: &CryptoContextDCRTPoly, key: &PrivateKeyDCRTPoly);
+        fn EvalRotateKeyGen(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                             indexList: &CxxVector<i32>,
-                            publicKey: /* null() */ SharedPtr<PublicKeyImpl>);
-        fn EvalAtIndexKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+                            publicKey: /* GenNullPublicKey() */ &PublicKeyDCRTPoly);
+        fn EvalAtIndexKeyGen(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                              indexList: &CxxVector<i32>,
-                             publicKey: /* null() */ SharedPtr<PublicKeyImpl>);
+                             publicKey: /* GenNullPublicKey() */ &PublicKeyDCRTPoly);
         fn EvalCKKStoFHEWPrecompute(self: &CryptoContextDCRTPoly, scale: /* 1.0 */ f64);
         fn MakePackedPlaintext(self: &CryptoContextDCRTPoly, value: &CxxVector<i64>,
                                noiseScaleDeg: /* 1 */ usize, level: /* 0 */ u32)
                                -> UniquePtr<Plaintext>;
-        fn EncryptByPublicKey(self: &CryptoContextDCRTPoly, publicKey: SharedPtr<PublicKeyImpl>,
+        fn EncryptByPublicKey(self: &CryptoContextDCRTPoly, publicKey: &PublicKeyDCRTPoly,
                               plaintext: &Plaintext) -> UniquePtr<CiphertextDCRTPoly>;
-        fn EncryptByPrivateKey(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+        fn EncryptByPrivateKey(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                                plaintext: &Plaintext) -> UniquePtr<CiphertextDCRTPoly>;
         fn EvalAddByCiphertexts(self: &CryptoContextDCRTPoly, ciphertext1: &CiphertextDCRTPoly,
                                 ciphertext2: &CiphertextDCRTPoly) -> UniquePtr<CiphertextDCRTPoly>;
@@ -711,16 +714,16 @@ pub mod ffi
                               levelBudget: /* {5, 4} */ &CxxVector<u32>,
                               dim1: /* {0, 0} */ &CxxVector<u32>, slots: /* 0 */ u32,
                               correctionFactor: /* 0 */ u32, precompute: /* true */ bool);
-        fn EvalBootstrapKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+        fn EvalBootstrapKeyGen(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                                slots: u32);
         fn DecryptByPrivateKeyAndCiphertext(self: &CryptoContextDCRTPoly,
-                                            privateKey: SharedPtr<PrivateKeyImpl>,
+                                            privateKey: &PrivateKeyDCRTPoly,
                                             ciphertext: &CiphertextDCRTPoly,
                                             plaintext: Pin<&mut Plaintext>)
                                             -> UniquePtr<DecryptResult>;
         fn DecryptByCiphertextAndPrivateKey(self: &CryptoContextDCRTPoly,
                                             ciphertext: &CiphertextDCRTPoly,
-                                            privateKey: SharedPtr<PrivateKeyImpl>,
+                                            privateKey: &PrivateKeyDCRTPoly,
                                             plaintext: Pin<&mut Plaintext>)
                                             -> UniquePtr<DecryptResult>;
         fn GetRingDimension(self: &CryptoContextDCRTPoly) -> u32;
@@ -815,27 +818,28 @@ pub mod ffi
         fn LevelReduceInPlace(self: &CryptoContextDCRTPoly, ciphertext: &CiphertextDCRTPoly,
                               evalKey: &EvalKeyDCRTPoly, levels: /* 1 */ usize);
         fn ReEncrypt(self: &CryptoContextDCRTPoly, ciphertext: &CiphertextDCRTPoly,
-                     evalKey: &EvalKeyDCRTPoly, publicKey: /* null() */ SharedPtr<PublicKeyImpl>)
+                     evalKey: &EvalKeyDCRTPoly,
+                     publicKey: /* GenNullPublicKey() */ &PublicKeyDCRTPoly)
                      -> UniquePtr<CiphertextDCRTPoly>;
-        fn KeySwitchGen(self: &CryptoContextDCRTPoly, oldPrivateKey: SharedPtr<PrivateKeyImpl>,
-                        newPrivateKey: SharedPtr<PrivateKeyImpl>) -> UniquePtr<EvalKeyDCRTPoly>;
-        fn ReKeyGen(self: &CryptoContextDCRTPoly, oldPrivateKey: SharedPtr<PrivateKeyImpl>,
-                    newPublicKey: SharedPtr<PublicKeyImpl>) -> UniquePtr<EvalKeyDCRTPoly>;
+        fn KeySwitchGen(self: &CryptoContextDCRTPoly, oldPrivateKey: &PrivateKeyDCRTPoly,
+                        newPrivateKey: &PrivateKeyDCRTPoly) -> UniquePtr<EvalKeyDCRTPoly>;
+        fn ReKeyGen(self: &CryptoContextDCRTPoly, oldPrivateKey: &PrivateKeyDCRTPoly,
+                    newPublicKey: &PublicKeyDCRTPoly) -> UniquePtr<EvalKeyDCRTPoly>;
         fn MultiKeySwitchGen(self: &CryptoContextDCRTPoly,
-                             originalPrivateKey: SharedPtr<PrivateKeyImpl>,
-                             newPrivateKey: SharedPtr<PrivateKeyImpl>, evalKey: &EvalKeyDCRTPoly)
+                             originalPrivateKey: &PrivateKeyDCRTPoly,
+                             newPrivateKey: &PrivateKeyDCRTPoly, evalKey: &EvalKeyDCRTPoly)
                              -> UniquePtr<EvalKeyDCRTPoly>;
         fn MultiAddEvalKeys(self: &CryptoContextDCRTPoly, evalKey1: &EvalKeyDCRTPoly,
                             evalKey2: &EvalKeyDCRTPoly, keyId: /* "" */ &CxxString)
                             -> UniquePtr<EvalKeyDCRTPoly>;
-        fn MultiMultEvalKey(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+        fn MultiMultEvalKey(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                             evalKey: &EvalKeyDCRTPoly, keyId: /* "" */ &CxxString)
                             -> UniquePtr<EvalKeyDCRTPoly>;
         fn MultiAddEvalMultKeys(self: &CryptoContextDCRTPoly, evalKey1: &EvalKeyDCRTPoly,
                                 evalKey2: &EvalKeyDCRTPoly, keyId: /* "" */ &CxxString)
                                 -> UniquePtr<EvalKeyDCRTPoly>;
-        fn EvalSumKeyGen(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
-                         publicKey: /* null() */ SharedPtr<PublicKeyImpl>);
+        fn EvalSumKeyGen(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
+                         publicKey: /* GenNullPublicKey() */ &PublicKeyDCRTPoly);
         fn EvalCKKStoFHEWKeyGen(self: &CryptoContextDCRTPoly, keyPair: &KeyPairDCRTPoly,
                                 lwesk: &LWEPrivateKey);
         fn EvalFHEWtoCKKSKeyGen(self: &CryptoContextDCRTPoly, keyPair: &KeyPairDCRTPoly,
@@ -846,12 +850,12 @@ pub mod ffi
         fn GetModulus(self: &CryptoContextDCRTPoly) -> u64;
         fn GetRootOfUnity(self: &CryptoContextDCRTPoly) -> u64;
         fn MultipartyDecryptLead(self: &CryptoContextDCRTPoly, ciphertextVec: &VectorOfCiphertexts,
-                                 privateKey: SharedPtr<PrivateKeyImpl>)
+                                 privateKey: &PrivateKeyDCRTPoly)
                                  -> UniquePtr<VectorOfCiphertexts>;
         fn MultipartyDecryptMain(self: &CryptoContextDCRTPoly, ciphertextVec: &VectorOfCiphertexts,
-                                 privateKey: SharedPtr<PrivateKeyImpl>)
+                                 privateKey: &PrivateKeyDCRTPoly)
                                  -> UniquePtr<VectorOfCiphertexts>;
-        fn IntMPBootDecrypt(self: &CryptoContextDCRTPoly, privateKey: SharedPtr<PrivateKeyImpl>,
+        fn IntMPBootDecrypt(self: &CryptoContextDCRTPoly, privateKey: &PrivateKeyDCRTPoly,
                             ciphertext: &CiphertextDCRTPoly, a: &CiphertextDCRTPoly)
                             -> UniquePtr<VectorOfCiphertexts>;
         fn EvalMinSchemeSwitching(self: &CryptoContextDCRTPoly, ciphertext: &CiphertextDCRTPoly,
@@ -958,14 +962,14 @@ mod tests
         _cc.Enable(ffi::PKESchemeFeature::LEVELEDSHE);
 
         let _key_pair = _cc.KeyGen();
-        _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+        _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
 
         let mut _index_list = CxxVector::<i32>::new();
         _index_list.pin_mut().push(1);
         _index_list.pin_mut().push(2);
         _index_list.pin_mut().push(-1);
         _index_list.pin_mut().push(-2);
-        _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
+        _cc.EvalRotateKeyGen(&_key_pair.GetPrivateKey(), &_index_list, &ffi::GenNullPublicKey());
 
         let mut _vector_of_ints_1 = CxxVector::<i64>::new();
         _vector_of_ints_1.pin_mut().push(1);
@@ -1012,9 +1016,9 @@ mod tests
         _vector_of_ints_3.pin_mut().push(12);
         let _plain_text_3 = _cc.MakePackedPlaintext(&_vector_of_ints_3, 1, 0);
 
-        let _cipher_text_1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_1);
-        let _cipher_text_2 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_2);
-        let _cipher_text_3 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_3);
+        let _cipher_text_1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_1);
+        let _cipher_text_2 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_2);
+        let _cipher_text_3 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_3);
 
         let _cipher_text_add_1_2 = _cc.EvalAddByCiphertexts(&_cipher_text_1, &_cipher_text_2);
         let _cipher_text_add_result = _cc.EvalAddByCiphertexts(&_cipher_text_add_1_2, &_cipher_text_3);
@@ -1028,17 +1032,17 @@ mod tests
         let _cipher_text_rot_4 = _cc.EvalRotate(&_cipher_text_1, -2);
 
         let mut _plain_text_add_result = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_add_result, _plain_text_add_result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_add_result, _plain_text_add_result.pin_mut());
         let mut _plain_text_mult_result = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_mult_result, _plain_text_mult_result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_mult_result, _plain_text_mult_result.pin_mut());
         let mut _plain_text_rot_1 = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_1, _plain_text_rot_1.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_1, _plain_text_rot_1.pin_mut());
         let mut _plain_text_rot_2 = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_2, _plain_text_rot_2.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_2, _plain_text_rot_2.pin_mut());
         let mut _plain_text_rot_3 = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_3, _plain_text_rot_3.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_3, _plain_text_rot_3.pin_mut());
         let mut _plain_text_rot_4 = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_cipher_text_rot_4, _plain_text_rot_4.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_cipher_text_rot_4, _plain_text_rot_4.pin_mut());
 
         _plain_text_rot_1.SetLength(_vector_of_ints_1.len());
         _plain_text_rot_2.SetLength(_vector_of_ints_1.len());
@@ -1078,11 +1082,11 @@ mod tests
         println!("CKKS scheme is using ring dimension {}\n", _cc.GetRingDimension());
 
         let _key_pair = _cc.KeyGen();
-        _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+        _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
         let mut _index_list = CxxVector::<i32>::new();
         _index_list.pin_mut().push(1);
         _index_list.pin_mut().push(-2);
-        _cc.EvalRotateKeyGen(_key_pair.GetPrivateKey(), &_index_list, SharedPtr::<ffi::PublicKeyImpl>::null());
+        _cc.EvalRotateKeyGen(&_key_pair.GetPrivateKey(), &_index_list, &ffi::GenNullPublicKey());
 
         let mut _x_1 = CxxVector::<f64>::new();
         _x_1.pin_mut().push(0.25);
@@ -1110,8 +1114,8 @@ mod tests
         println!("Input x1: {}", _p_txt_1.GetString());
         println!("Input x2: {}", _p_txt_2.GetString());
 
-        let _c1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_p_txt_1);
-        let _c2 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_p_txt_2);
+        let _c1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_p_txt_1);
+        let _c2 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_p_txt_2);
 
         let _c_add = _cc.EvalAddByCiphertexts(&_c1, &_c2);
         let _c_sub = _cc.EvalSubByCiphertexts(&_c1, &_c2);
@@ -1123,32 +1127,32 @@ mod tests
         let mut _result = ffi::GenEmptyPlainText();
         println!("\nResults of homomorphic computations:");
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c1, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c1, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("x1 = {}Estimated precision in bits: {}", _result.GetString(), _result.GetLogPrecision());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_add, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_add, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("x1 + x2 = {}Estimated precision in bits: {}",_result.GetString(), _result.GetLogPrecision());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_sub, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_sub, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("x1 - x2 = {}", _result.GetString());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_scalar, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_scalar, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("4 * x1 = {}", _result.GetString());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_mul, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_mul, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("x1 * x2 = {}", _result.GetString());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_rot_1, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_rot_1, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("\nIn rotations, very small outputs (~10^-10 here) correspond to 0's:");
         println!("x1 rotate by 1 = {}", _result.GetString());
 
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_c_rot_2, _result.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_c_rot_2, _result.pin_mut());
         _result.SetLength(_batch_size.try_into().unwrap());
         println!("x1 rotate by -2 = {}", _result.GetString());
     }
@@ -1231,9 +1235,9 @@ mod tests
         let _plain_text_1 = _cc.MakeCKKSPackedPlaintextByVectorOfComplex(&_input, 1, 0, SharedPtr::<ffi::DCRTPolyParams>::null(), 0);
         let _key_pair = _cc.KeyGen();
         print!("Generating evaluation key for homomorphic multiplication...");
-        _cc.EvalMultKeyGen(_key_pair.GetPrivateKey());
+        _cc.EvalMultKeyGen(&_key_pair.GetPrivateKey());
         println!("Completed.\n");
-        let _cipher_text_1 = _cc.EncryptByPublicKey(_key_pair.GetPublicKey(), &_plain_text_1);
+        let _cipher_text_1 = _cc.EncryptByPublicKey(&_key_pair.GetPublicKey(), &_plain_text_1);
 
         let mut _start = Instant::now();
         let _result = _cc.EvalPoly(&_cipher_text_1, &_coefficients_1);
@@ -1244,10 +1248,10 @@ mod tests
         let _time_eval_poly_2 = _start.elapsed();
 
         let mut _plain_text_dec = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result, _plain_text_dec.pin_mut());
         _plain_text_dec.SetLength(_encoded_length);
         let mut _plain_text_dec_2 = ffi::GenEmptyPlainText();
-        _cc.DecryptByPrivateKeyAndCiphertext(_key_pair.GetPrivateKey(), &_result_2, _plain_text_dec_2.pin_mut());
+        _cc.DecryptByPrivateKeyAndCiphertext(&_key_pair.GetPrivateKey(), &_result_2, _plain_text_dec_2.pin_mut());
         _plain_text_dec_2.SetLength(_encoded_length);
 
         println!("\n Original Plaintext #1:");