IBR-DTN  1.0.0
HashProtocol.cpp
Go to the documentation of this file.
1 /*
2  * HashProtocol.cpp
3  *
4  * Copyright (C) 2014 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  * Thomas Schrader <schrader.thomas@gmail.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22 
26 #include "core/BundleCore.h"
27 #include <iomanip>
28 
29 #include <openssl/sha.h>
30 #include <openssl/rand.h>
31 #define RANDOM_NUMBER_LENGTH 256
32 
33 namespace dtn
34 {
35  namespace security
36  {
37  HashProtocol::HashState::~HashState()
38  {
39  }
40 
42  : KeyExchangeProtocol(manager, 3)
43  {
44  }
45 
47  {
48  }
49 
50  KeyExchangeSession* HashProtocol::createSession(const dtn::data::EID &peer, unsigned int uniqueId)
51  {
52  return new KeyExchangeSession(getProtocol(), peer, uniqueId, new HashState());
53  }
54 
56  {
57  // get session state
58  HashState &state = session.getState<HashState>();
59 
60  state.random = std::vector<char>(RANDOM_NUMBER_LENGTH);
61 
62  if(!RAND_bytes((unsigned char*)&state.random[0], RANDOM_NUMBER_LENGTH))
63  {
64  throw ibrcommon::Exception("Error while generating random number");
65  }
66 
67  // get local public key
69 
70  KeyExchangeData request(KeyExchangeData::REQUEST, session);
71  sha256(request, std::string(state.random.begin(), state.random.end()) + pkey.getData());
72 
73  manager.submit(session, request);
74  }
75 
77  {
78  // get session state
79  HashState &state = session.getState<HashState>();
80 
81  switch (data.getStep())
82  {
83  case 0:
84  {
85  if (data.getAction() == KeyExchangeData::REQUEST)
86  {
87  // copy commitment from message to session
88  const std::string data_str = data.str();
89  state.commitment = std::vector<char>(data_str.begin(), data_str.end());
90 
91  // generate random bytes
92  state.random = std::vector<char>(RANDOM_NUMBER_LENGTH);
93  if(!RAND_bytes((unsigned char*)&state.random[0], RANDOM_NUMBER_LENGTH))
94  {
95  throw ibrcommon::Exception("Error while generating random number");
96  }
97 
98  // get local public key
100 
101  KeyExchangeData response(KeyExchangeData::RESPONSE, session);
102  sha256(response, std::string(&state.random[0], RANDOM_NUMBER_LENGTH) + pkey.getData());
103 
104  manager.submit(session, response);
105  }
106  else
107  {
108  const std::string data_str = data.str();
109  state.commitment = std::vector<char>(data_str.begin(), data_str.end());
110 
111  // get local public key
113 
114  KeyExchangeData request(KeyExchangeData::REQUEST, session);
115  request.setStep(1);
116 
117  const dtn::data::BundleString rnd_data(std::string(state.random.begin(), state.random.end()));
118  request << rnd_data;
119 
120  const dtn::data::BundleString publicK(pkey.getData());
121  request << publicK;
122 
123  manager.submit(session, request);
124  }
125  break;
126  }
127 
128  case 1:
129  {
130  if (data.getAction() == KeyExchangeData::REQUEST)
131  {
133  data >> r;
134 
136  data >> pub;
137 
138  //test commitment
139  std::string commitment = std::string(&state.commitment[0], 2*SHA256_DIGEST_LENGTH);
140 
141  std::stringstream controlStream;
142  sha256(controlStream, r + pub);
143  if (commitment != controlStream.str())
144  {
145  throw ibrcommon::Exception("Error while comparing commitment");
146  }
147 
148  // write key in tmp file
150 
151  const std::string random(&state.random[0], RANDOM_NUMBER_LENGTH);
152 
153  // get local public key
155 
156  KeyExchangeData response(KeyExchangeData::RESPONSE, session);
157  response.setStep(1);
158 
159  const dtn::data::BundleString rnd_data(std::string(state.random.begin(), state.random.end()));
160  response << rnd_data;
161 
162  const dtn::data::BundleString publicK(pkey.getData());
163  response << publicK;
164 
165  manager.submit(session, response);
166 
168  sha256(event, r + pub + random + pkey.getData());
169  KeyExchangeEvent::raise(session.getPeer(), event);
170  }
171  else
172  {
174  data >> r;
175 
177  data >> pub;
178 
179  //test commitment
180  const std::string commitment = std::string(&state.commitment[0], 2*SHA256_DIGEST_LENGTH);
181  std::stringstream controlStream;
182  sha256(controlStream, r + pub);
183 
184  if (commitment != controlStream.str())
185  {
186  throw ibrcommon::Exception("Error while comparing commitment");
187  }
188 
189  // write key in tmp file
191 
192  const std::string random(state.random.begin(), state.random.end());
193 
194  // get local public key
196 
198  sha256(event, random + pkey.getData() + r + pub);
199  event.setAction(KeyExchangeData::HASH_COMMIT);
200  KeyExchangeEvent::raise(session.getPeer(), event);
201  }
202  break;
203  }
204  }
205  }
206 
207  void HashProtocol::sha256(std::ostream &stream, const std::string &data)
208  {
209  unsigned char hash[SHA256_DIGEST_LENGTH];
210  SHA256((const unsigned char*) data.c_str(), data.size(), hash);
211 
212  for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
213  {
214  stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
215  }
216  }
217  } /* namespace security */
218 } /* namespace dtn */
static SecurityKeyManager & getInstance()
virtual void begin(KeyExchangeSession &session, KeyExchangeData &data)
const dtn::data::EID & getPeer() const
static dtn::data::EID local
Definition: BundleCore.h:79
virtual KeyExchangeSession * createSession(const dtn::data::EID &peer, unsigned int uniqueId)
void putKey(const std::string &data, const dtn::security::SecurityKey::KeyType type, const dtn::security::SecurityKey::TrustLevel trust) const
virtual void step(KeyExchangeSession &session, KeyExchangeData &data)
virtual const std::string getData() const
Definition: SecurityKey.cpp:64
#define RANDOM_NUMBER_LENGTH
dtn::security::SecurityKey get(const dtn::data::EID &ref, const dtn::security::SecurityKey::KeyType type=dtn::security::SecurityKey::KEY_UNSPEC) const
HashProtocol(KeyExchangeManager &manager)
virtual void submit(KeyExchangeSession &session, const KeyExchangeData &data)=0
static void raise(const dtn::data::EID &eid, const dtn::security::KeyExchangeData &data)