const KEYSIZE = SHA512_DIGEST_LENGTH + 4; // 4 bytes on the "salt"
unsigned char * pubkey = (unsigned char *) OPENSSL_malloc (10000),
* privkey = (unsigned char *) OPENSSL_malloc (10000); // public and private key buffers
AnsiString pub, prv, userid, paypass; // strings for storing public, private keys and their password
unsigned char md [KEYSIZE] = {0}; // there will be a password hash
unsigned int i = ParamCount ();
paypass = "rAnDom_PaSs" ;
EC_GROUP * group = EC_GROUP_new_by_curve_name (NID_sect571r1); // choose an elliptic curve
EC_GROUP_set_point_conversion_form (group, POINT_CONVERSION_UNCOMPRESSED);
EC_KEY * x = EC_KEY_new ();
EC_KEY_set_group (x, group);
BIO * out = BIO_new (BIO_s_mem ()); // We will write in memory
// Code to slow down the brute force
env_md_ctx_st mdctx; // context for hash
EVP_MD_CTX_init (& mdctx);
EVP_DigestInit_ex (& mdctx, EVP_sha512 (), NULL); // Hashing Algorithm - SHA512
EVP_DigestUpdate (& mdctx, paypass.c_str (), strlen (paypass.c_str ())); // Hash password for the first time
for (i = 0; i <0x20000; i ++) {
memcpy (md, mdctx.md_data, SHA512_DIGEST_LENGTH); // copy hash to array
md [64] = i ^ md [0] ^ md [7] ^ md [5] ^ md [23]; // calculate additional 4 bytes
md [65] = i ^ md [1] ^ md [9] ^ md [6] ^ md [53]; // based on previous hash
md [66] = i ^ md [3] ^ md [25] ^ md [11] ^ md [48]; // they will be so-called round salt
md [67] = i ^ md [8] ^ md [18] ^ md [17] ^ md [2];
EVP_DigestUpdate (& mdctx, md, KEYSIZE); // and hash the previous hash + salt
}
EVP_DigestFinal (& mdctx, md, NULL); // finish counting the hash
EVP_MD_CTX_cleanup (& mdctx);
EC_KEY_generate_key (x); // generate key pair
PEM_write_bio_ECPrivateKey ( out , x, EVP_aes_256_cbc (), md, KEYSIZE, NULL, NULL); // write the AES-256 encrypted key pair with the key calculated in the previous step
BIO_flush ( out );
i = BIO_read ( out , privkey, 10,000); // find out the number of bytes written
// for fidelity let's compress ZLIB
zByte * compr;
uLong comprLenPrv = 1000 * sizeof ( int );
zByte * comprPrv = (zByte *) calloc ((uInt) comprLenPrv, 1);
compress2 (comprPrv, & comprLenPrv, ( const Bytef *) privkey, i, Z_BEST_COMPRESSION);
OPENSSL_free (privkey);
BIO_free ( out );
out = BIO_new (BIO_s_mem ()); // another buffer for the public key
PEM_write_bio_EC_PUBKEY ( out , x); // write it to memory in PEM format
BIO_flush ( out );
BIO_read ( out , pubkey, 10,000); // read it in a piece of memory
// Magic code to copy the private encrypted key to the byte array
TByteDynArray cp;
cp.set_length (comprLenPrv);
for (i = 0; i <comprLenPrv; i ++) {
cp [i] = comprPrv [i];
}
// copy the public key into the string
AnsiString pubk;
pubk.sprintf ( "% s" , pubkey);
// release the memory
free (comprPrv);
OPENSSL_free (pubkey);
BIO_free ( out );
EC_KEY_free (x);
....
unsigned long i;
unsigned char * x;
unsigned char buf [1024] = {0};
// Sign the line with the key. key - read and decoded key from item 1. s - rendome line.
ECDSA_SIG * sig = ECDSA_do_sign (s.c_str (), s.Length (), key);
x = buf;
i = i2d_ECDSA_SIG (sig, & x); // convert to binary form
x = buf;
ECDSA_SIG_free (sig);
// so that the signature can be copied - convert it to base64
BIO * b64 = BIO_new (BIO_f_base64 ());
BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL); // no line breaks
BIO * mem = BIO_new (BIO_s_mem ());
mem = BIO_push (b64, mem);
BIO_write (mem, & buf, i);
BIO_flush (mem);
char * res;
BIO_get_mem_data (mem, & res);
mAnswer-> Text = res; // output the result to the user.
int ssl_VerifySignature ( const char * key, const char * str, const char * csig).
{
OpenSSL_add_all_algorithms ();
BIO * bkey = BIO_new (BIO_s_mem ());
BIO_write (bkey, key, ( int ) strlen (key));
BIO_flush (bkey);
EC_KEY * ec = PEM_read_bio_EC_PUBKEY (bkey, NULL, NULL, NULL); // read the public key
BIO_free (bkey);
if (! ec) return -2;
unsigned long i;
unsigned char * x;
unsigned char buf [1024] = {0};
BIO * b64 = BIO_new (BIO_f_base64 ());
BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
BIO * mem = BIO_new (BIO_s_mem ());
BIO_write (mem, csig, ( int ) strlen (csig));
mem = BIO_push (b64, mem);
x = buf;
i = BIO_read (mem, x, 1024);
x = buf;
ECDSA_SIG * sig = ECDSA_SIG_new ();
sig = d2i_ECDSA_SIG (& sig, ( const unsigned char **) & x, i); // read the signature
i = ECDSA_do_verify (( const unsigned char *) str, ( int ) strlen (str), sig, ec); // check string signature
BIO_free_all (mem);
ECDSA_SIG_free (sig);
return i;
}
Source: https://habr.com/ru/post/96116/
All Articles