IBR-DTN  1.0.0
SecurityKey.cpp
Go to the documentation of this file.
1 /*
2  * SecurityKey.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
23 #include <ibrcommon/ssl/SHA256Stream.h>
24 #include <ibrcommon/Logger.h>
25 #include <fstream>
26 #include <sstream>
27 #include <iomanip>
28 
29 #include <openssl/sha.h>
30 #include <openssl/pem.h>
31 #include <openssl/err.h>
32 
33 namespace dtn
34 {
35  namespace security
36  {
38  : type(KEY_UNSPEC), trustlevel(NONE)
39  {}
40 
42  {}
43 
45  {
46  RSA_free(key);
47  }
48 
49  void SecurityKey::free(EVP_PKEY* key)
50  {
51  EVP_PKEY_free(key);
52  }
53 
55  {
56  return getFingerprint() == key.getFingerprint();
57  }
58 
59  ibrcommon::File SecurityKey::getMetaFilename() const
60  {
61  return ibrcommon::File(file.getPath() + ".txt");
62  }
63 
64  const std::string SecurityKey::getData() const
65  {
66  std::ifstream stream(file.getPath().c_str(), ios::in);
67  std::stringstream ss;
68 
69  ss << stream.rdbuf();
70 
71  stream.close();
72 
73  return ss.str();
74  }
75 
77  {
78  switch (type)
79  {
80  case KEY_PRIVATE:
81  return getPrivateRSA();
82  case KEY_PUBLIC:
83  return getPublicRSA();
84  default:
85  return NULL;
86  }
87  }
88 
89  EVP_PKEY* SecurityKey::getEVP() const
90  {
91  EVP_PKEY* ret = EVP_PKEY_new();
92  FILE * pkey_file = fopen(file.getPath().c_str(), "r");
93 
94  switch (type)
95  {
96  case KEY_PRIVATE:
97  {
98  ret = PEM_read_PrivateKey(pkey_file, &ret, NULL, NULL);
99  break;
100  }
101 
102  case KEY_PUBLIC:
103  {
104  ret = PEM_read_PUBKEY(pkey_file, &ret, NULL, NULL);
105  break;
106  }
107 
108  default:
109  ret = NULL;
110  break;
111  }
112 
113  fclose(pkey_file);
114  return ret;
115  }
116 
117  const std::string SecurityKey::getFingerprint() const
118  {
119  switch (type)
120  {
121  case KEY_PRIVATE:
122  {
123  RSA* rsa = getPrivateRSA();
124  std::string ret = getFingerprint(rsa);
125  free(rsa);
126  return ret;
127  }
128  case KEY_PUBLIC:
129  {
130  RSA* rsa = getPublicRSA();
131  std::string ret = getFingerprint(rsa);
132  free(rsa);
133  return ret;
134  }
135  default:
136  {
137  return getFingerprint(file);
138  }
139  }
140  }
141 
142  RSA* SecurityKey::getPrivateRSA() const
143  {
144  RSA *rsa = RSA_new();
145 
146  FILE * rsa_pkey_file = fopen(file.getPath().c_str(), "r");
147  if (!rsa_pkey_file) {
148  IBRCOMMON_LOGGER_ex(critical) << "Failed to open " << file.getPath() << IBRCOMMON_LOGGER_ENDL;
149  throw ibrcommon::Exception("Failed to open " + file.getPath());
150  }
151  if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa, NULL, NULL)) {
152  IBRCOMMON_LOGGER_ex(critical) << "Error loading RSA private key file: " << file.getPath() << IBRCOMMON_LOGGER_ENDL;
153  ERR_print_errors_fp(stderr);
154  throw ibrcommon::Exception("Error loading RSA private key file: " + file.getPath());
155  }
156  fclose(rsa_pkey_file);
157  return rsa;
158  }
159 
160  RSA* SecurityKey::getPublicRSA() const
161  {
162  RSA *rsa = RSA_new();
163 
164  FILE * rsa_pkey_file = fopen(file.getPath().c_str(), "r");
165  if (!rsa_pkey_file) {
166  IBRCOMMON_LOGGER_ex(critical) << "Failed to open " << file.getPath() << IBRCOMMON_LOGGER_ENDL;
167  throw ibrcommon::Exception("Failed to open " + file.getPath());
168  }
169  if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa, NULL, NULL)) {
170  IBRCOMMON_LOGGER_ex(critical) << "Error loading RSA public key file: " << file.getPath() << IBRCOMMON_LOGGER_ENDL;
171  ERR_print_errors_fp(stderr);
172  throw ibrcommon::Exception("Error loading RSA public key file: " + file.getPath());
173  }
174  fclose(rsa_pkey_file);
175  return rsa;
176  }
177 
178  std::string SecurityKey::getFingerprint(const ibrcommon::File &file)
179  {
180  // create a hash stream
181  ibrcommon::SHA256Stream sha;
182 
183  // open the file
184  ifstream stream(file.getPath().c_str());
185 
186  // hash the contents of the file
187  if (!stream.good()) {
188  sha << stream.rdbuf() << std::flush;
189  }
190 
191  // convert bytes to hex fingerprint
192  std::stringstream fingerprint;
193  while (sha.good())
194  {
195  fingerprint << std::hex << std::setw(2) << std::setfill('0') << (int)sha.get();
196  }
197 
198  return fingerprint.str();
199  }
200 
202  {
203  unsigned char *p = NULL;
204  int length = i2d_RSA_PUBKEY(rsa, &p);
205 
206  std::string ret = "";
207  if (length > 0)
208  {
209  ret = std::string((const char*)p, length);
210  }
211  else
212  {
213  OPENSSL_free(p);
214  free(rsa);
215  throw(ibrcommon::Exception("Error while parsing rsa key"));
216  }
217 
218  unsigned char hash[SHA256_DIGEST_LENGTH];
219  SHA256(p, length, hash);
220 
221  std::stringstream stream;
222  for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
223  {
224  stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
225  }
226 
227  OPENSSL_free(p);
228  return stream.str();
229  }
230  }
231 }
ibrcommon::File file
Definition: SecurityKey.h:83
virtual EVP_PKEY * getEVP() const
Definition: SecurityKey.cpp:89
rsa_st RSA
Definition: SecurityBlock.h:35
static void free(RSA *key)
Definition: SecurityKey.cpp:44
virtual const std::string getData() const
Definition: SecurityKey.cpp:64
virtual RSA * getRSA() const
Definition: SecurityKey.cpp:76
bool operator==(const SecurityKey &key)
Definition: SecurityKey.cpp:54
virtual const std::string getFingerprint() const
ibrcommon::File getMetaFilename() const
Definition: SecurityKey.cpp:59