diff --git a/coreapi/chat.c b/coreapi/chat.c
index d6ce2cd5bef01171a6d9184f7011defdaab4bc3b..4c5870125c04586697353b958ab80506dd583992 100644
--- a/coreapi/chat.c
+++ b/coreapi/chat.c
@@ -18,12 +18,10 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <bctoolbox/defs.h>
+#include "bctoolbox/defs.h"
 
 #include "belle-sip/belle-sip.h"
 
-#include "ortp/b64.h"
-
 #include "linphone/core.h"
 #include "linphone/lpconfig.h"
 #include "linphone/wrapper_utils.h"
diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp
index b3b6e3004a57df0ce9bd2ee237da7274b2b43960..895a936b3952ef0df8e187a561a1a9cacc0d0298 100644
--- a/src/c-wrapper/api/c-chat-message.cpp
+++ b/src/c-wrapper/api/c-chat-message.cpp
@@ -23,8 +23,6 @@
 #include "linphone/utils/utils.h"
 #include "linphone/wrapper_utils.h"
 
-#include "ortp/b64.h"
-
 #include "address/address.h"
 #include "c-wrapper/c-wrapper.h"
 #include "chat/chat-message/chat-message-p.h"
diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp
index 61d21794889750b46f6dcfe53d3de772f7d7016d..fbe4d5f36f240de2af3e4df97b7aac4ece28176a 100644
--- a/src/chat/chat-message/chat-message.cpp
+++ b/src/chat/chat-message/chat-message.cpp
@@ -50,16 +50,12 @@
 #include "logger/logger.h"
 #include "sip-tools/sip-headers.h"
 
-#include "ortp/b64.h"
-
 #include "db/main-db-key-p.h"
 #include "db/main-db-p.h"
 // =============================================================================
 
 using namespace std;
 
-using namespace B64_NAMESPACE;
-
 LINPHONE_BEGIN_NAMESPACE
 
 ChatMessagePrivate::ChatMessagePrivate(const std::shared_ptr<AbstractChatRoom> &cr, ChatMessage::Direction dir)
diff --git a/src/chat/encryption/lime-x3dh-encryption-engine.cpp b/src/chat/encryption/lime-x3dh-encryption-engine.cpp
index dcf80e09f034c01b49111e824e51753026c1f51b..39c2ac9d0a955c7f4d29bf60dc5069431337a528 100644
--- a/src/chat/encryption/lime-x3dh-encryption-engine.cpp
+++ b/src/chat/encryption/lime-x3dh-encryption-engine.cpp
@@ -19,8 +19,9 @@
  */
 
 #include "bctoolbox/crypto.h"
+#include "bctoolbox/crypto.hh"
+#include "bctoolbox/defs.h"
 #include "bctoolbox/exception.hh"
-#include <bctoolbox/defs.h>
 
 #include "account/account.h"
 #include "c-wrapper/c-wrapper.h"
@@ -375,7 +376,7 @@ ChatMessageModifier::Result LimeX3dhEncryptionEngine::processOutgoingMessage(con
 				    // ---------------------------------------------- HEADERS
 
 				    for (const lime::RecipientData &recipient : filteredRecipients) {
-					    string cipherHeaderB64 = encodeBase64(recipient.DRmessage);
+					    string cipherHeaderB64 = bctoolbox::encodeBase64(recipient.DRmessage);
 					    Content *cipherHeader = new Content();
 					    cipherHeader->setBodyFromLocale(cipherHeaderB64);
 					    cipherHeader->setContentType(ContentType::LimeKey);
@@ -388,7 +389,7 @@ ChatMessageModifier::Result LimeX3dhEncryptionEngine::processOutgoingMessage(con
 				    // ---------------------------------------------- MESSAGE
 
 				    const vector<uint8_t> *binaryCipherMessage = cipherMessage.get();
-				    string cipherMessageB64 = encodeBase64(*binaryCipherMessage);
+				    string cipherMessageB64 = bctoolbox::encodeBase64(*binaryCipherMessage);
 				    Content *cipherMessage = new Content();
 				    cipherMessage->setBodyFromLocale(cipherMessageB64);
 				    cipherMessage->setContentType(ContentType::OctetStream);
@@ -544,8 +545,8 @@ ChatMessageModifier::Result LimeX3dhEncryptionEngine::processIncomingMessage(con
 		return ChatMessageModifier::Result::Error;
 	}
 
-	vector<uint8_t> decodedCipherHeader = decodeBase64(cipherHeader);
-	vector<uint8_t> decodedCipherMessage = decodeBase64(cipherMessage);
+	vector<uint8_t> decodedCipherHeader = bctoolbox::decodeBase64(cipherHeader);
+	vector<uint8_t> decodedCipherMessage = bctoolbox::decodeBase64(cipherMessage);
 	vector<uint8_t> plainMessage{};
 
 	try {
@@ -741,7 +742,7 @@ list<EncryptionParameter> LimeX3dhEncryptionEngine::getEncryptionParameters(cons
 
 	// Encode to base64 and append to the parameter list
 	list<pair<string, string>> paramList;
-	string IkB64 = encodeBase64(Ik);
+	string IkB64 = bctoolbox::encodeBase64(Ik);
 	// "Ik" is deprecated, use "lime-Ik" instead. "lime-Ik" parsing is supported since 01/03/2020.
 	// Switch here to lime-Ik to start publishing lime-Ik instead of Ik
 	paramList.push_back(make_pair("Ik", IkB64));
@@ -794,8 +795,8 @@ void LimeX3dhEncryptionEngine::mutualAuthentication(MSZrtpContext *zrtpContext,
 	}
 
 	// Convert to vectors and decode base64
-	vector<uint8_t> localIk = decodeBase64(LocalIkB64);
-	vector<uint8_t> remoteIk = decodeBase64(RemoteIkB64);
+	vector<uint8_t> localIk = bctoolbox::decodeBase64(LocalIkB64);
+	vector<uint8_t> remoteIk = bctoolbox::decodeBase64(RemoteIkB64);
 
 	// Concatenate identity keys in the right order
 	vector<uint8_t> vectorAuxSharedSecret;
@@ -841,7 +842,7 @@ void LimeX3dhEncryptionEngine::authenticationVerified(
 		}
 	}
 
-	vector<uint8_t> remoteIk = decodeBase64(remoteIkB64);
+	vector<uint8_t> remoteIk = bctoolbox::decodeBase64(remoteIkB64);
 	const std::shared_ptr<Address> peerDeviceAddr = Address::create(peerDeviceId);
 
 	if (ms_zrtp_getAuxiliarySharedSecretMismatch(zrtpContext) == 2 /*BZRTP_AUXSECRET_UNSET*/) {
diff --git a/src/chat/encryption/lime-x3dh-encryption-engine.h b/src/chat/encryption/lime-x3dh-encryption-engine.h
index 6d1e815d59f4f1a0c4828c13a1a63d7a3a4b19ed..5355026a5972c59e61bd688682dd361979d397a3 100644
--- a/src/chat/encryption/lime-x3dh-encryption-engine.h
+++ b/src/chat/encryption/lime-x3dh-encryption-engine.h
@@ -33,30 +33,6 @@
 
 LINPHONE_BEGIN_NAMESPACE
 
-inline std::string encodeBase64(const std::vector<uint8_t> &input) {
-	const unsigned char *inputBuffer = input.data();
-	size_t inputLength = input.size();
-	size_t encodedLength = 0;
-	bctbx_base64_encode(NULL, &encodedLength, inputBuffer, inputLength); // set encodedLength to the correct value
-	unsigned char *encodedBuffer = new unsigned char[encodedLength];     // allocate encoded buffer with correct length
-	bctbx_base64_encode(encodedBuffer, &encodedLength, inputBuffer, inputLength); // real encoding
-	std::string output((char *)encodedBuffer);
-	delete[] encodedBuffer;
-	return output;
-}
-
-inline std::vector<uint8_t> decodeBase64(const std::string &input) {
-	const unsigned char *inputBuffer = (const unsigned char *)input.data();
-	size_t inputLength = input.size();
-	size_t decodedLength = 0;
-	bctbx_base64_decode(NULL, &decodedLength, inputBuffer, inputLength); // set decodedLength to the correct value
-	unsigned char *decodedBuffer = new unsigned char[decodedLength];     // allocate decoded buffer with correct length
-	bctbx_base64_decode(decodedBuffer, &decodedLength, inputBuffer, inputLength); // real decoding
-	std::vector<uint8_t> output(decodedBuffer, decodedBuffer + decodedLength);
-	delete[] decodedBuffer;
-	return output;
-}
-
 class LimeManager : public lime::LimeManager {
 public:
 	LimeManager(const std::string &db_access,
diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h
index 617b81ce70a98435277113f24966de9de9792ce5..6090feffae22a702d68c6412b90d95c3def9f6b3 100644
--- a/src/conference/session/media-session-p.h
+++ b/src/conference/session/media-session-p.h
@@ -25,6 +25,8 @@
 #include <queue>
 #include <vector>
 
+#include "bctoolbox/crypto.hh"
+
 #include "call-session-p.h"
 #include "ms2-streams.h"
 
@@ -111,8 +113,8 @@ public:
 		return streamsGroup->getCurrentOfferAnswerContext().remoteMediaDescription;
 	}
 
-	int setupEncryptionKey(SalSrtpCryptoAlgo &crypto, MSCryptoSuite suite, unsigned int tag) const;
-	std::vector<SalSrtpCryptoAlgo> generateNewCryptoKeys() const;
+	int setupEncryptionKey(SalSrtpCryptoAlgo &crypto, MSCryptoSuite suite, unsigned int tag);
+	std::vector<SalSrtpCryptoAlgo> generateNewCryptoKeys();
 
 	const LinphoneStreamInternalStats *getStreamInternalStats(LinphoneStreamType type) const;
 	const std::shared_ptr<NatPolicy> getNatPolicy() const {
@@ -223,7 +225,7 @@ private:
 	void selectOutgoingIpVersion();
 
 	void forceStreamsDirAccordingToState(std::shared_ptr<SalMediaDescription> &md);
-	bool generateB64CryptoKey(size_t keyLength, std::string &keyOut, size_t keyOutSize) const;
+	bool generateB64CryptoKey(size_t keyLength, std::string &keyOut);
 	void makeLocalMediaDescription(bool localIsOfferer,
 	                               const bool supportsCapabilityNegotiationAttributes,
 	                               const bool offerNegotiatedMediaProtocolOnly,
@@ -402,6 +404,8 @@ private:
 
 	SalMediaRecord lastRemoteRecordingState = SalMediaRecordOff;
 
+	bctoolbox::RNG mRng; // Used to the generation of crypto keys
+
 	L_DECLARE_PUBLIC(MediaSession);
 };
 
diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp
index efce62b266fede61dde32c9787a90a7801618d9c..d91bd77c05edd482a276a648b49822c3d847d318 100644
--- a/src/conference/session/media-session.cpp
+++ b/src/conference/session/media-session.cpp
@@ -20,6 +20,7 @@
 
 // #include <iomanip>
 // #include <math.h>
+
 #include <algorithm>
 
 #include "account/account.h"
@@ -44,7 +45,7 @@
 
 #include "linphone/core.h"
 
-#include <bctoolbox/defs.h>
+#include "bctoolbox/defs.h"
 
 #include <mediastreamer2/mediastream.h>
 #include <mediastreamer2/msequalizer.h>
@@ -53,7 +54,6 @@
 
 #include <mediastreamer2/msrtt4103.h>
 #include <mediastreamer2/msvolume.h>
-#include <ortp/b64.h>
 
 #include "conference.h"
 #include "private.h"
@@ -1464,36 +1464,12 @@ void MediaSessionPrivate::forceStreamsDirAccordingToState(std::shared_ptr<SalMed
 	}
 }
 
-bool MediaSessionPrivate::generateB64CryptoKey(size_t keyLength, std::string &keyOut, size_t keyOutSize) const {
-	uint8_t *tmp = (uint8_t *)ms_malloc0(keyLength);
-	if (!sal_get_random_bytes(tmp, keyLength)) {
-		lError() << "Failed to generate random key";
-		ms_free(tmp);
-		return false;
-	}
-	size_t b64Size = b64::b64_encode((const char *)tmp, keyLength, nullptr, 0);
-	if (b64Size == 0) {
-		lError() << "Failed to get b64 result size";
-		ms_free(tmp);
-		return false;
-	}
-	if (b64Size >= keyOutSize) {
-		lError() << "Insufficient room for writing base64 SRTP key";
-		ms_free(tmp);
-		return false;
-	}
-	// Initialize characters with \0
-	char *key = new char[keyOutSize]{'\0'};
-	b64Size = b64::b64_encode((const char *)tmp, keyLength, key, keyOutSize);
-	if (b64Size == 0) {
-		lError() << "Failed to b64 encode key";
-		ms_free(tmp);
-		delete[] key;
+bool MediaSessionPrivate::generateB64CryptoKey(size_t keyLength, std::string &keyOut) {
+	vector<uint8_t> src = mRng.randomize(keyLength);
+	keyOut = bctoolbox::encodeBase64(src);
+	if (keyOut.empty()) {
 		return false;
 	}
-	keyOut.assign(key);
-	delete[] key;
-	ms_free(tmp);
 	return true;
 }
 
@@ -2639,7 +2615,7 @@ void MediaSessionPrivate::makeLocalMediaDescription(bool localIsOfferer,
 	if (op) op->setLocalMediaDescription(localDesc);
 }
 
-int MediaSessionPrivate::setupEncryptionKey(SalSrtpCryptoAlgo &crypto, MSCryptoSuite suite, unsigned int tag) const {
+int MediaSessionPrivate::setupEncryptionKey(SalSrtpCryptoAlgo &crypto, MSCryptoSuite suite, unsigned int tag) {
 	crypto.tag = tag;
 	crypto.algo = suite;
 	size_t keylen = 0;
@@ -2667,7 +2643,7 @@ int MediaSessionPrivate::setupEncryptionKey(SalSrtpCryptoAlgo &crypto, MSCryptoS
 		case MS_CRYPTO_SUITE_INVALID:
 			break;
 	}
-	if ((keylen == 0) || !generateB64CryptoKey(keylen, crypto.master_key, SAL_SRTP_KEY_SIZE)) {
+	if ((keylen == 0) || !generateB64CryptoKey(keylen, crypto.master_key)) {
 		lError() << "Could not generate SRTP key";
 		crypto.algo = MS_CRYPTO_SUITE_INVALID;
 		return -1;
@@ -2936,7 +2912,7 @@ static LinphoneSrtpSuite MSCryptoSuite2LinphoneSrtpSuite(const MSCryptoSuite sui
 	}
 }
 
-std::vector<SalSrtpCryptoAlgo> MediaSessionPrivate::generateNewCryptoKeys() const {
+std::vector<SalSrtpCryptoAlgo> MediaSessionPrivate::generateNewCryptoKeys() {
 	L_Q();
 	std::vector<SalSrtpCryptoAlgo> cryptos;
 	const bool doNotUseParams = (direction == LinphoneCallIncoming) && (state == CallSession::State::Idle);
diff --git a/src/sal/sal_stream_configuration.h b/src/sal/sal_stream_configuration.h
index 09f102bcc00c0bedea54a25000cd75453dcf84a3..ea7e83e0d7589245ef870c273752b19460d561a2 100644
--- a/src/sal/sal_stream_configuration.h
+++ b/src/sal/sal_stream_configuration.h
@@ -49,9 +49,6 @@ typedef struct SalIceRemoteCandidate {
 	int port = 0;
 } SalIceRemoteCandidate;
 
-/*sufficient for 256bit keys encoded in base 64*/
-#define SAL_SRTP_KEY_SIZE 128
-
 typedef struct SalSrtpCryptoAlgo {
 	unsigned int tag = 0;
 	MSCryptoSuite algo = MS_CRYPTO_SUITE_INVALID;
diff --git a/tester/tester.cpp b/tester/tester.cpp
index 71751e7053a03ed5f9c16e5507131e6b90d2043c..00d976ca4518d2a55f6cceca3aa8caa8dbdd8b8f 100644
--- a/tester/tester.cpp
+++ b/tester/tester.cpp
@@ -36,7 +36,7 @@
 #include "logger/logger.h"
 
 #ifdef HAVE_LIME_X3DH
-#include "chat/encryption/lime-x3dh-encryption-engine.h"
+#include "bctoolbox/crypto.hh"
 #endif // HAVE_LIME_X3DH
 
 bool is_filepath_encrypted(const char *filepath) {
@@ -112,7 +112,7 @@ char *lime_get_userIk(LinphoneCoreManager *mgr, char *gruu) {
 			const size_t public_key_size = ik_blob.get_len() / 2;
 			ik_blob.read(0, (char *)(ikRaw.data()), public_key_size); // Read the public key
 			std::vector<uint8_t> ik(ikRaw.cbegin(), ikRaw.cbegin() + public_key_size);
-			std::string ikStr = LinphonePrivate::encodeBase64(ik);
+			std::string ikStr = bctoolbox::encodeBase64(ik);
 			if (!ikStr.empty()) {
 				ret = ms_strdup(ikStr.c_str());
 			}