Security Research · Desktop
Alkebulan Crypto
Status
Internal research prototype
Stack
[ THE THESIS ]
A C++ cryptography prototype where every primitive is visible.
Alkebulan Crypto is an internal security research prototype built from raw C++ and OpenSSL to study wallet encryption, signatures, hashing, file integrity, and deterministic DID generation. The project is presented through what the research implemented: key generation, AES encryption, ECDSA signatures, PBKDF2 derivation, SHA hashing, and country-code-based identifiers.
Internal research prototype · C++17 · OpenSSL · No framework dependencies
SECTION 01 — SECURITY RESEARCH
A C++ cryptography prototype where every primitive is visible
This is internal research, not a launch announcement. The work demonstrates the security surface directly: key derivation, encryption, signatures, hashing, file integrity, and deterministic DID generation.
Raw OpenSSL · no Ethereum · no Solana
Every cryptographic operation is an explicit OpenSSL function call. Nothing is hidden behind a framework abstraction. Every byte of security is auditable.
Password never touches disk
Password is stretched into an AES key via PBKDF2 at unlock time and erased from memory after use. An attacker with full disk access has an .enc blob and salts — nothing else.
Identifiers are generated from explicit inputs
Country and currency metadata are modeled as structured inputs. Test DIDs are generated from country code, timestamp, entropy, SHA-256, and decimal extraction.
Signatures are ECDSA secp256k1
Same curve Bitcoin uses. Proven, widely audited, constant-time hardware support. No experimental curves, no custom signature schemes.
SECTION 02 — PRIVATE KEY ENCRYPTION FLOW
Password → PBKDF2 → AES-256-CBC → .enc on disk
User Password
never written to disk
PBKDF2
KEY DERIVATIONAES-256-CBC
SYMMETRIC ENCRYPTION.enc file on disk · password never stored
{
"salt": "bP5DMFPezf58H+Sc2kdkpg==",
"iv": "7Aet73ltSCIsNkHywqXnag==",
"data": "OdGJgMP1e6YGXkywGvlBRRMGy2TucmxRo..."
}SECTION 03 — CRYPTOGRAPHIC STACK
Every operation mapped to an explicit, auditable algorithm
SECTION 04 — DID SYSTEM
DID generator built from country code, entropy, and SHA-256
country code + timestamp + random hex → SHA-256 → first 12 bytes → 9-digit test DID
Country Code · e.g. UG
Unix Timestamp
Random Hex Entropy
SHA-256 →
first 12 bytes →
9-digit decimal
GH167540927 · Ghana
KE104139596 · Kenya
UG236319457 · Uganda
SECTION 05 — ENGINEERING HIGHLIGHTS
Why this was built this way
AUDITABILITY
No framework abstraction between code and cipher
Every PBKDF2 round, every AES block, every ECDSA signature is an explicit OpenSSL call in the source tree. The crypto surface area is exactly what I wrote, not what a framework hides.
→ security layer, line-by-line readable
KEY SAFETY
100k PBKDF2 iterations + random IV per encrypt
Offline brute-force cost on a derived AES key is multiplied by the iteration count. A fresh 16-byte IV per encrypt prevents ciphertext reuse attacks even if the same key is used twice.
→ password stays in memory only
DID MODEL
Country metadata modeled as first-class inputs
Most crypto experiments reduce identity to a hex wallet address. This prototype keeps country metadata explicit, then derives test DIDs through deterministic hashing rather than hand-authored identifiers.
→ country-scoped · hash-derived · collision-safe
SECTION 06 — CODE PROOF
PBKDF2 + AES-256-CBC · raw OpenSSL C++
Verbatim core of the key-encryption path.
crypto.cpp
cpp
// crypto.cpp — excerpt · PBKDF2 → AES-256-CBC
// Raw OpenSSL, no frameworks. Every byte is auditable.
static std::vector<unsigned char> deriveKey(
const std::string& password,
const std::vector<unsigned char>& salt
) {
std::vector<unsigned char> key(32); // 256-bit AES key
if (PKCS5_PBKDF2_HMAC(
password.data(), password.size(),
salt.data(), salt.size(),
100000, // iteration count
EVP_sha256(),
key.size(), key.data()) != 1) {
throw std::runtime_error("PBKDF2 failed");
}
return key;
}
static std::vector<unsigned char> encryptPrivateKey(
const std::vector<unsigned char>& privkey,
const std::string& password
) {
auto salt = randomBytes(16);
auto iv = randomBytes(16);
auto key = deriveKey(password, salt);
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key.data(), iv.data());
std::vector<unsigned char> out(privkey.size() + AES_BLOCK_SIZE);
int len = 0, total = 0;
EVP_EncryptUpdate(ctx, out.data(), &len, privkey.data(), privkey.size());
total += len;
EVP_EncryptFinal_ex(ctx, out.data() + total, &len);
total += len;
out.resize(total);
EVP_CIPHER_CTX_free(ctx);
return writeEncFile(salt, iv, out); // {salt, iv, data} as base64
}