Diana Software
QCryptoRSA.cc
Go to the documentation of this file.
1 #include "QCryptoRSA.hh"
2 #include "QDiana.hh"
3 #include "QError.hh"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sstream>
7 
8 #include <openssl/rsa.h>
9 #include <openssl/pem.h>
10 #include <openssl/err.h>
11 
12 #include <arpa/inet.h> /* For htonl() */
13 
15 
16 
17 
18 QCryptoRSA::QCryptoRSA(const std::string& pKey, const QCryptoRSA::Mode mode, bool nopad)
19 {
20  FILE* inputKeyFile = fopen(pKey.c_str(),"r");
21  fMode = mode;
22  fRSA = NULL;
23  if(!inputKeyFile) {
25  std::stringstream msg;
26  msg<<"Cannot open file: "<<pKey;
27  err.SetDescription(__FILE__,__LINE__,msg.str());
28  DianaThrow(err);
29  }
30 
31  if(mode == ENCRYPT) {
32  if (!PEM_read_RSA_PUBKEY(inputKeyFile, &fRSA, NULL, NULL)) {
34  err.SetDescription(__FILE__,__LINE__,"Error loading RSA Public Key File");
35  DianaThrow(err);
36  }
37  } else if(mode == DECRYPT) {
38  if (!PEM_read_RSAPrivateKey(inputKeyFile, &fRSA, NULL, NULL)) {
40  err.SetDescription(__FILE__,__LINE__,"Error loading RSA Private Key File");
41  DianaThrow(err);
42  }
43  } else {
45  err.SetDescription(__FILE__,__LINE__,"Mode must be encrypt or decrypt");
46  DianaThrow(err);
47  }
48  if(inputKeyFile) fclose(inputKeyFile);
49  fOutput = (unsigned char*)malloc(sizeof(char)*RSA_size(fRSA));
50  fNoPadding = nopad;
51  if(fNoPadding) {
52  fRandomSize = 1;
53  fBeginPad = 1;
54  srand(time(0));
55  fMsgLength = RSA_size(fRSA)-fRandomSize-fBeginPad;
56  } else {
57  fBeginPad = 0;
58  fRandomSize = 0;
59  fMsgLength = RSA_size(fRSA)-11;
60  }
61  if(fMsgLength < 0) {
63  err.SetDescription(__FILE__,__LINE__,"RSA key length too short");
64  DianaThrow(err);
65  }
66 
67 }
68 
70 {
71 }
72 
73 std::vector<unsigned char> QCryptoRSA::ConvertString(const std::string& message)
74 {
75  std::vector<unsigned char> output(message.size());
76  for(size_t i = 0; i < message.size(); i++) {
77  output[i] = message[i];
78  }
79  return output;
80 }
81 
82 std::string QCryptoRSA::ConvertString(const std::vector<unsigned char>& message)
83 {
84  std::string output(message.size(), ' ');
85  for(size_t i = 0; i < message.size(); i++) {
86  output[i] = (char)message[i];
87  }
88  return output;
89 }
90 std::vector<unsigned char> QCryptoRSA::ConvertHex(const std::string& message)
91 {
92  size_t size = message.size();
93  if(size % 2 != 0) {
95  err.SetDescription(__FILE__,__LINE__,"String size is odd, must be even");
96  DianaThrow(err);
97  }
98  size_t outsize = size/2;
99  std::vector<unsigned char> output(outsize);
100  char byte[3];
101  for(size_t i = 0; i < message.size(); i+=2) {
102  byte[0] = message[i];
103  byte[1] = message[i+1];
104  byte[2] = '\0';
105  unsigned int tmp;
106  sscanf(byte, "%02x", &tmp);
107  output[i/2] = (unsigned char)tmp;
108  }
109  return output;
110 }
111 
112 std::string QCryptoRSA::ConvertHex(const std::vector<unsigned char>& message)
113 {
114  std::string output(message.size()*2,' ');
115  char byte[3];
116  for(size_t i = 0; i < message.size(); i++) {
117  snprintf(byte,3,"%02x",message[i]);
118  output[i*2] = byte[0];
119  output[i*2+1] = byte[1];
120  }
121  return output;
122 }
123 
124 std::vector<unsigned char> QCryptoRSA::ConvertDouble(const double message)
125 {
126  size_t size = sizeof(message);
127  std::vector<unsigned char> output(size);
128  const unsigned char* input = reinterpret_cast<const unsigned char*>(&message);
129  for(size_t i = 0; i < size; i++) {
130  output[i] = input[i];
131  }
132  return output;
133 }
134 
135 double QCryptoRSA::ConvertDouble(const std::vector<unsigned char>& message)
136 {
137  double output;
138  size_t size = sizeof(output);
139  if(message.size() != size) {
141  std::stringstream msg;
142  msg<<"QCryptoRSA::ConvertDouble: Input message size ("<<message.size()<<")"
143  <<" differs from "<<size;
144  err.SetDescription(__FILE__,__LINE__,msg.str());
145  DianaThrow(err);
146  }
147  unsigned char* coutput = reinterpret_cast<unsigned char*>(&output);
148  for(size_t i = 0; i < size; i++) {
149  coutput[i] = message[i];
150  }
151  return output;
152 }
153 
154 std::vector<unsigned char> QCryptoRSA::Process(const std::vector<unsigned char>& message) const
155 {
156  int len_out,len_in;
157  len_in = message.size();
158  if(fMode == ENCRYPT) {
159  if(fNoPadding && len_in != fMsgLength) {
161  std::stringstream msg;
162  msg<<"Input message size ("<<message.size()<<")"
163  <<" differs from "<<fMsgLength<<" char";
164  err.SetDescription(__FILE__,__LINE__,msg.str());
165  DianaThrow(err);
166  } else if(!fNoPadding && len_in >=( fMsgLength)) {
168  std::stringstream msg;
169  msg<<"Input message too long ("<<message.size()<<")"
170  <<" must be shorter than "<<fMsgLength<<" char";
171  err.SetDescription(__FILE__,__LINE__,msg.str());
172  DianaThrow(err);
173  }
174 
175  len_in += fBeginPad;
176  unsigned char* input = ConvertArray(message,fRandomSize,fBeginPad);
177  for(size_t i = 0; i < fRandomSize; i++) {
178  input[len_in+i] = rand()%256;
179  }
180  len_in += fRandomSize;
181  if(fNoPadding) {
182  len_out = RSA_public_encrypt(len_in, input,
183  fOutput, fRSA, RSA_NO_PADDING);
184  } else {
185  len_out = RSA_public_encrypt(len_in, input,
186  fOutput, fRSA, RSA_PKCS1_PADDING);
187  }
188  } else {
189  unsigned char* input = ConvertArray(message);
190  if(fNoPadding) {
191  len_out = RSA_private_decrypt(len_in, input,
192  fOutput, fRSA, RSA_NO_PADDING);
193  } else {
194  len_out = RSA_private_decrypt(len_in, input,
195  fOutput, fRSA, RSA_PKCS1_PADDING);
196  }
197  }
198  if(len_out == -1) {
200  std::stringstream msg;
201  char buf[128];
202  ERR_error_string(ERR_get_error(), buf);
203  msg<<"RSA failed with "<<buf;
204  err.SetDescription(__FILE__,__LINE__,msg.str());
205  DianaThrow(err);
206  }
207  int start = 0;
208  if(fMode == DECRYPT) {
209  len_out -= fRandomSize+fBeginPad;
210  start = fBeginPad;
211  }
212 
213  return ConvertArray(fOutput+start,len_out);
214 
215 }
216 
217 unsigned char* QCryptoRSA::ConvertArray(const std::vector<unsigned char>& input, const size_t pad, const size_t beginpad) const
218 {
219  unsigned char* output = (unsigned char*) malloc(sizeof(unsigned char)*(input.size()+pad+beginpad));
220 
221  for(size_t i = 0; i < beginpad; i++) {
222  output[i] = 0;
223  }
224  for(size_t i = beginpad; i < input.size()+beginpad; i++) {
225  output[i] = input[i-beginpad];
226  }
227  for(size_t i = input.size()+beginpad; i < input.size()+pad+beginpad; i++) {
228  output[i] = 0;
229  }
230 
231  return output;
232 }
233 
234 std::vector<unsigned char> QCryptoRSA::ConvertArray(const unsigned char* input, const size_t n) const
235 {
236  std::vector<unsigned char> output(n);
237  for(size_t i = 0; i < n; i++) {
238  output[i] = input[i];
239  }
240  return output;
241 }
242 
243 
244 void QCryptoRSA::Print(const char* header, const unsigned char* data, const size_t n)
245 {
246  printf("%s: ",header);
247  for(size_t c = 0; c < n; c++) printf("%x",data[c]);
248  printf("\n");
249 
250 
251 }
252 
253 
err
Definition: CheckOF.C:114
ClassImp(QCryptoRSA) QCryptoRSA
Definition: QCryptoRSA.cc:14
#define DianaThrow(obj)
Definition: QDianaDebug.hh:26
@ QERR_UNKNOWN_ERR
Definition: QError.hh:108
@ QERR_CANNOT_OPEN_FILE
Definition: QError.hh:33
@ QERR_SIZE_NOT_MATCH
Definition: QError.hh:31
fixed-size encryption with the raw RSA algorithm. For envelope see QCryptoRSAEnvelope.
Definition: QCryptoRSA.hh:18
unsigned char * ConvertArray(const std::vector< unsigned char > &input, const size_t pad=0, const size_t beginpad=0) const
Definition: QCryptoRSA.cc:217
static std::vector< unsigned char > ConvertDouble(const double message)
convert from double
Definition: QCryptoRSA.cc:124
std::vector< unsigned char > Process(const std::vector< unsigned char > &message) const
encrypt or decrypt message
Definition: QCryptoRSA.cc:154
int fMsgLength
Definition: QCryptoRSA.hh:62
virtual ~QCryptoRSA()
destructor
Definition: QCryptoRSA.cc:69
RSA * fRSA
Definition: QCryptoRSA.hh:58
unsigned char * fOutput
Definition: QCryptoRSA.hh:60
bool fNoPadding
Definition: QCryptoRSA.hh:61
size_t fRandomSize
Definition: QCryptoRSA.hh:63
static std::vector< unsigned char > ConvertString(const std::string &message)
convert from string
Definition: QCryptoRSA.cc:73
QCryptoRSA(const std::string &pKey, const Mode mode, bool nopad=true)
constructor: if ENCRYPT provide public key, otherwise provide private key
void Print(const char *header, const unsigned char *data, const size_t n)
Definition: QCryptoRSA.cc:244
Mode fMode
Definition: QCryptoRSA.hh:56
static std::vector< unsigned char > ConvertHex(const std::string &message)
convert from hex-string
Definition: QCryptoRSA.cc:90
Mode
encrypt or decrypt mode
Definition: QCryptoRSA.hh:21
size_t fBeginPad
Definition: QCryptoRSA.hh:64
error class with error type and description
Definition: QError.hh:115