/* This file is part of Bolixo. Bolixo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bolixo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bolixo. If not, see . */ #include #include #include #include #include using namespace std; using std::unique_ptr; #include #include #include #include #include #include #define ASSERT assert using BN_ptr = std::unique_ptr; //using RSA_ptr = std::unique_ptr; using EVP_KEY_ptr = std::unique_ptr; using BIO_FILE_ptr = std::unique_ptr; static int sign( const char *msg, EVP_PKEY *key, unsigned char *&sig, size_t &sig_len) { int ret = -1; sig = NULL; sig_len = 0; /* Create the Message Digest Context */ EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (mdctx != NULL){ /* Initialise the DigestSign operation - SHA-256 has been selected as the message digest function in this example */ if(EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key) == 1){ /* Call update with the message */ if(EVP_DigestSignUpdate(mdctx, msg, strlen(msg)) == 1){ // Finalise the DigestSign operation // First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the // signature. Length is returned in slen */ if(EVP_DigestSignFinal(mdctx, NULL, &sig_len) == 1){ //printf ("sig_len=%lu\n",sig_len); // Allocate memory for the signature based on size in slen sig = (unsigned char*)OPENSSL_malloc(sizeof(unsigned char) * sig_len); if (sig != NULL){ // Obtain the signature if(EVP_DigestSignFinal(mdctx, sig, &sig_len) == 1){ /* Success */ #if 0 for (unsigned i=0; i0){ //printf ("line=%s\n",line); private_key += line; } BIO_free_all(bio); } { BIO *bio = BIO_new(BIO_s_mem()); PEM_write_bio_PUBKEY(bio, pkey.get()); char line[1000]; while(BIO_gets(bio,line,sizeof(line))>0){ //printf ("line=%s\n",line); public_key += line; } BIO_free_all(bio); } if (write_files){ BIO_FILE_ptr pem1(BIO_new_file("/tmp/rsa-public-1.pem", "w"), ::BIO_free); BIO_FILE_ptr pem2(BIO_new_file("/tmp/rsa-public-2.pem", "w"), ::BIO_free); BIO_FILE_ptr pem3(BIO_new_file("/tmp/rsa-private-1.pem", "w"), ::BIO_free); BIO_FILE_ptr pem4(BIO_new_file("/tmp/rsa-private-2.pem", "w"), ::BIO_free); BIO_FILE_ptr pem5(BIO_new_file("/tmp/rsa-private-3.pem", "w"), ::BIO_free); BIO_FILE_ptr der1(BIO_new_file("/tmp/rsa-public.der", "w"), ::BIO_free); BIO_FILE_ptr der2(BIO_new_file("/tmp/rsa-private.der", "w"), ::BIO_free); // Write public key in ASN.1/DER rc = i2d_RSAPublicKey_bio(der1.get(), rsa); ASSERT(rc == 1); // Write public key in PKCS PEM rc = PEM_write_bio_RSAPublicKey(pem1.get(), rsa); ASSERT(rc == 1); // Write public key in Traditional PEM rc = PEM_write_bio_PUBKEY(pem2.get(), pkey.get()); ASSERT(rc == 1); ////////// // Write private key in ASN.1/DER rc = i2d_RSAPrivateKey_bio(der2.get(), rsa); ASSERT(rc == 1); // Write private key in PKCS PEM. rc = PEM_write_bio_PrivateKey(pem3.get(), pkey.get(), NULL, NULL, 0, NULL, NULL); ASSERT(rc == 1); // Write private key in PKCS PEM rc = PEM_write_bio_PKCS8PrivateKey(pem4.get(), pkey.get(), NULL, NULL, 0, NULL, NULL); ASSERT(rc == 1); // Write private key in Traditional PEM rc = PEM_write_bio_RSAPrivateKey(pem5.get(), rsa, NULL, NULL, 0, NULL, NULL); ASSERT(rc == 1); } return rsa; } #else static void get_private_key (EVP_PKEY *pkey, PARAM_STRING passphrase, string &private_key) { BIO *bio = BIO_new(BIO_s_mem()); PEM_write_bio_PrivateKey(bio, pkey,EVP_aes_192_cbc(), (unsigned char*)passphrase.ptr,strlen(passphrase.ptr), 0, 0); char line[1000]; while(BIO_gets(bio,line,sizeof(line))>0){ //printf ("line=%s\n",line); private_key += line; } BIO_free_all(bio); } static void get_public_key (EVP_PKEY *pkey, string &public_key) { BIO *bio = BIO_new(BIO_s_mem()); PEM_write_bio_PUBKEY(bio, pkey); char line[1000]; while(BIO_gets(bio,line,sizeof(line))>0){ //printf ("line=%s\n",line); public_key += line; } BIO_free_all(bio); } static void generate_new(unsigned nbbits, string &private_key, string &public_key, PARAM_STRING passphrase, bool write_files) { private_key.clear(); public_key.clear(); ENGINE *e = nullptr; EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,e); if (ctx == nullptr){ fprintf (stderr,"ctx=%p\n",ctx); exit (-1); } int rc; #if 0 // Does not work for RSA rc = EVP_PKEY_paramgen_init (ctx); printf ("paramgen_init rc=%d\n",rc); const OSSL_PARAM *params = EVP_PKEY_CTX_gettable_params(ctx); printf ("params=%p\n",params); #endif // Generate key rc = EVP_PKEY_keygen_init (ctx); printf ("keygen_init rc=%d\n",rc); rc = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbbits); printf ("keygen_bits rc=%d\n",rc); EVP_PKEY *retkey=nullptr; rc = EVP_PKEY_generate(ctx,&retkey); printf ("generate rc=%d\n",rc); get_private_key(retkey,passphrase,private_key); get_public_key(retkey,public_key); //printf ("retkey.size=%d bits=%d\n",EVP_PKEY_get_size(retkey),EVP_PKEY_get_bits(retkey)); //printf ("private_key=%s\npublic_key=%s\n",private_key.c_str(),public_key.c_str()); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(retkey); } #endif static EVP_PKEY *testsign_load_private (PARAM_STRING p, PARAM_STRING passphrase) { BIO *bio = BIO_new_mem_buf((void*)p.ptr, strlen(p.ptr)); EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL,NULL,(void*)passphrase.ptr); BIO_free_all (bio); return pkey; } static EVP_PKEY *testsign_load_public (PARAM_STRING p) { BIO *bio = BIO_new_mem_buf((void*)p.ptr, strlen(p.ptr)); EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL,NULL,NULL); BIO_free_all (bio); return pkey; } int main (int argc, char *argv[]) { glocal int ret = -1; glocal unsigned nbverify = 1; glocal unsigned nbgen = 1; glocal unsigned nbbits = 2048; glocal const char *message = "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" "This is a message that goes like this\n" ; glocal.ret = (argc,argv); setproginfo ("testsign",VERSION,"..."); setarg (' ',"nbverify","Number of sign/verifies",glocal.nbverify,false); setarg (' ',"nbgen","Number of key generation",glocal.nbgen,false); setarg (' ',"nbbits","Size in bits of the generated key",glocal.nbbits,false); string modified_message = string(glocal.message) + "something"; const char *passphrase = "this is secret"; int ret = -1; #ifdef OLDRSA RSA *rsa = NULL; #endif string private_key,public_key; for (unsigned i=0; i return glocal.ret; }