// $Header: /cvs/gled-1.2/GledCore/Gled/GKeyRSA.cxx,v 1.3 2005/03/11 17:50:16 matevz Exp $
// Copyright (C) 1999-2005, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.
//______________________________________________________________________
// GKeyRSA
//
// Example of trivial use:
//
// GKeyRSA k1, k2;
// TBuffer b(TBuffer::kWrite);
// try {
// k1.ReadPubKey(PubKeyFile(mSaturnIdentity));
// k1.GenerateSecret();
// k1.SendSecret(b);
//
// b.SetReadMode();
// b.SetBufferOffset(0);
//
// k2.ReadPrivKey(PrivKeyFile(mSaturnIdentity));
// k2.ReceiveSecret(b);
// if(k1.MatchSecrets(k2)) {
// cout <<"Secret comparison successfuln";
// } else {
// cout <<"Secret comparison failedn";
// }
// }
// catch(string exc) {
// cout << "encode test failed: "<< exc << endl;
// }
//
#include "GKeyRSA.h"
#include <Gled/GThread.h>
#include <TBuffer.h>
#include <TRandom2.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
ClassImp(GKeyRSA)
/**************************************************************************/
bool GKeyRSA::init_done = false;
GMutex* GKeyRSA::s_ssl_mutexen = 0;
void GKeyRSA::init_ssl()
{
if(init_done) return;
SSL_library_init();
SSL_load_error_strings();
int nl = CRYPTO_num_locks();
//printf("GKeyRSA::init_ssl setting up %d locksn", nl);
s_ssl_mutexen = new GMutex[nl];
CRYPTO_set_locking_callback(ssl_locker_foo);
CRYPTO_set_id_callback(ssl_id_foo);
init_done = true;
}
void GKeyRSA::ssl_locker_foo(int mode, int n, const char *file, int line)
{
if(mode & CRYPTO_LOCK) {
//printf("GKeyRSA::ssl_locker locking %dn", n);
s_ssl_mutexen[n].Lock();
} else {
//printf("GKeyRSA::ssl_locker unlocking %dn", n);
s_ssl_mutexen[n].Unlock();
}
}
unsigned long GKeyRSA::ssl_id_foo()
{
return GThread::RawSelf();
}
/**************************************************************************/
/**************************************************************************/
bool GKeyRSA::check_error()
{
mSslError = ERR_get_error();
return mSslError;
}
const char* GKeyRSA::error_string()
{
return ERR_error_string(mSslError, 0);
}
/**************************************************************************/
/**************************************************************************/
GKeyRSA::GKeyRSA()
{
mSecret = 0;
mSecretLen = 0;
bIsPrivate = false;
pKey = 0;
mSslError = 0;
}
GKeyRSA::~GKeyRSA()
{
delete pKey;
delete [] mSecret;
}
/**************************************************************************/
void GKeyRSA::ReadPubKey(const char* file)
{
string _eh("GKeyRSA::ReadPubKey ");
if(pKey) { delete pKey; bIsPrivate = false; }
FILE* fp = fopen(file, "r");
if(!fp) throw(_eh + "file '" + file + "' not found");
pKey = PEM_read_RSA_PUBKEY(fp, 0, 0, 0);
fclose(fp);
if(check_error()) {
pKey = 0;
throw(_eh + error_string());
}
}
void GKeyRSA::ReadPrivKey(const char* file)
{
string _eh("GKeyRSA::ReadPrivKey ");
if(pKey) { delete pKey; bIsPrivate = false; }
FILE* fp = fopen(file, "r");
if(!fp) throw(_eh + "file " + file + " not found");
pKey = PEM_read_RSAPrivateKey(fp, 0, 0, 0);
fclose(fp);
if(check_error()) {
pKey = 0;
throw(_eh + error_string());
}
bIsPrivate = true;
}
/**************************************************************************/
void GKeyRSA::GenerateSecret()
{
static string _eh("GKeyRSA::GenerateSecret ");
assert(pKey);
UInt_t s;
FILE* fp = fopen("/dev/random", "r");
fread(&s, sizeof(UInt_t), 1, fp);
fclose(fp);
TRandom2 rnd(s);
int modlen = RSA_size(pKey);
mSecretLen = modlen - 41 - 1;
if(mSecret) delete mSecret;
mSecret = new unsigned char[mSecretLen];
for(int i=0; i<mSecretLen; ++i) {
mSecret[i] = (unsigned char)(255.99*rnd.Rndm());
}
}
void GKeyRSA::SendSecret(TBuffer& b)
{
static string _eh("GKeyRSA::SendSecret ");
int modlen = RSA_size(pKey);
unsigned char enc_secret[modlen];
Int_t lenmsg = RSA_public_encrypt(mSecretLen, mSecret, enc_secret,
pKey, RSA_PKCS1_OAEP_PADDING);
if(check_error())
throw(_eh + error_string());
b << lenmsg;
b.WriteFastArray((char*)enc_secret, lenmsg);
}
void GKeyRSA::ReceiveSecret(TBuffer& b)
{
static string _eh("GKeyRSA::ReceiveSecret ");
assert(pKey && bIsPrivate);
Int_t lenmsg;
b >> lenmsg;
unsigned char enc_secret[lenmsg];
unsigned char rec_secret[lenmsg];
b.ReadFastArray((char*)enc_secret, lenmsg);
mSecretLen = RSA_private_decrypt(lenmsg, enc_secret, rec_secret,
pKey, RSA_PKCS1_OAEP_PADDING);
if(check_error())
throw(_eh + error_string());
if(mSecret) delete mSecret;
mSecret = new unsigned char[mSecretLen];
for(int i=0; i<mSecretLen; ++i) mSecret[i] = rec_secret[i];
}
bool GKeyRSA::MatchSecrets(const GKeyRSA& a)
{
if(mSecretLen != a.mSecretLen) return false;
for(int i=0; i<mSecretLen; ++i) {
if(mSecret[i] != a.mSecret[i]) return false;
}
return true;
}
/**************************************************************************/
void GKeyRSA::StreamPubKey(TBuffer& b)
{
if(b.IsReading()) {
if(pKey) delete pKey;
pKey = RSA_new();
bIsPrivate = false;
Int_t ln, le;
b >> ln >> le;
char bn[ln], be[le];
b.ReadFastArray(bn, ln);
b.ReadFastArray(be, le);
pKey->n = BN_mpi2bn((unsigned char *)bn, ln, 0);
pKey->e = BN_mpi2bn((unsigned char *)be, le, 0);
} else {
Int_t ln, le;
ln = BN_bn2mpi(pKey->n, NULL);
le = BN_bn2mpi(pKey->e, NULL);
b << ln << le;
char bn[ln], be[le];
BN_bn2mpi(pKey->n, (unsigned char*)bn);
BN_bn2mpi(pKey->e, (unsigned char*)be);
b.WriteFastArray(bn, ln);
b.WriteFastArray(be, le);
}
}
ROOT page - Home page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.