Oops, I forgot to send the attachments.
#include "firma.hh"
#include openssl/rand.h
#include openssl/rsa.h
#include openssl/evp.h
#include openssl/blowfish.h
#include iostream
#include cstdio
const int KEY_SIZE = 1024;
Bytes_sha Sha1 (string contr);
Bytes_sha Blow (Bytes_sha data, Bytes_sha key);
void Firma::Generar (string contr, Bytes_sha pub, Bytes_sha priv) {
RSA *rsa;
RAND_load_file ("/dev/urandom", 2048);
unsigned char buf[KEY_SIZE * 10];
unsigned char* iter;
int key_len;
rsa = RSA_generate_key (KEY_SIZE, RSA_F4, 0, 0); // Generacion de claves
// Extraccion de clave publica
pub.reset (new Bytes);
iter = buf;
key_len = i2d_RSAPublicKey (rsa, iter);
for (int i = 0; i key_len; i++) pub-push_back (buf[i]);
// Extraccion de clave privada y encripcion con blowfish
iter = buf;
key_len = i2d_RSAPrivateKey (rsa, iter);
Bytes_sha tmp (new Bytes);
for (int i = 0; i key_len; i++) tmp-push_back (buf[i]);
Bytes_sha key = Sha1 (contr);
priv = Blow (tmp, key);
RSA_free(rsa);
}
Bytes_sha Firma::Firmar (string texto, const Bytes_sha priv, string contr) {
Bytes_sha retr (new Bytes (priv-size()));
Bytes_sha key = Sha1 (contr);
Bytes_sha priv_un = Blow (priv, key); // Contr. priv. sin encriptar
Bytes_sha cipher = Sha1 (texto);// Hash del texto
unsigned char* tmp = priv_un-begin();
RSA* rsa = d2i_RSAPrivateKey (0, tmp, priv_un-size());
int ret_len = RSA_private_encrypt (cipher-size(), cipher-begin(), retr-begin(),
rsa,
RSA_PKCS1_PADDING);
retr-resize (ret_len);
return retr;
}
bool Firma::Chequear (string texto, const Bytes_sha firma, const Bytes_sha pub) {
Bytes_sha cipher = Sha1 (texto);// Hash del texto
unsigned char* tmp = pub-begin();
RSA* rsa = d2i_RSAPublicKey (0, tmp, pub-size());
Bytes res (cipher-size());
RSA_public_decrypt (firma-size(), firma-begin(), res.begin(), rsa,
RSA_PKCS1_PADDING);
if (*cipher == res) return true;
return false;
}
void Dump (unsigned char* data, unsigned size, string id) {
cout id " " size ":\t";
for (unsigned i = 0; i size /* i 40*/; i++) printf ("%02x", data[i]);
cout endl;
}
// *** AUXILIARES *** //
Bytes_sha Sha1 (string contr) {
EVP_MD* evp = EVP_sha1();
EVP_MD_CTX* ctx = new EVP_MD_CTX;
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned hash_size;
EVP_DigestInit (ctx, evp);
EVP_DigestUpdate (ctx, contr.c_str(), contr.size());
EVP_DigestFinal (ctx, hash, hash_size);
Bytes_sha retr (new Bytes);
for (unsigned i = 0; i hash_size; i++) retr-push_back (hash[i]);
return retr;
}
Bytes_sha Blow (Bytes_sha data, Bytes_sha key) {
Bytes_sha retr (new Bytes);
BF_KEY* bf_key = new BF_KEY;
BF_set_key (bf_key, key-size(), key-begin());
retr-resize (data-size(), 0);
Bytes ivec (8); // 8 Bytes con 0
int num = 0;
BF_ofb64_encrypt (data-begin(), retr-begin(), data-size(), bf_key, ivec.begin(),
num);
return retr;
}
#if 0
// Obtenido de $ACE_ROOT/ace/SSL/SSL_Context.*
::CRYPTO_set_locking_callback (ACE_SSL_locking_callback);
ACE_SSL_locking_callback (int mode, int type, const char*, int) {
if (mode CRYPTO_LOCK)
ACE_OS::mutex_lock ((ACE_SSL_Context::lock_[type]));
else
ACE_OS::mutex_unlock ((ACE_SSL_Context::lock_[type]));
}
#endif
#ifndef Firma_hh
#define Firma_hh
#include string
#include vector
#include boost/smart_ptr.hpp
typedef vectorunsigned charBytes;
typedef boost::shared_ptrBytes Bytes_sha;
namespace Firma {
void Generar (string contr, Bytes_sha pub, Bytes_sha priv);
Bytes_sha Firmar (string texto, const Bytes_sha priv, string contr);
bool Chequear (string texto, const Bytes_sha firma, const Bytes_sha pub);
};
void Dump (unsigned char* data, unsigned size, string id);
#endif // Firma_hh
#include "firma.hh"
#include ctime
int main (int argc, char** argv) {
Bytes_sha pub, priv, firma;
string contr = "El padre angulo";
string texto = "Prueba de texto que se va a firmar.";
Firma::Generar (contr, pub, priv);
Dump (pub-begin(), pub-size(), "pub: ");
cout endl;
Dump (priv-begin(), priv-size(), "priv: ");
firma = Firma::Firmar (texto, priv, contr);
if (Firma::Chequear (texto, firma, pub)) cout "OK" endl;
else cout "Falla" endl;
cout endl;
cout endl;
}