IBR-DTNSuite  0.10
CipherStream.cpp
Go to the documentation of this file.
1 /*
2  * CipherStream.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 
24 namespace ibrcommon
25 {
26  CipherStream::CipherStream(std::ostream &stream, const CipherMode mode, const size_t buffer)
27  : std::ostream(this), _mode(mode), _stream(stream), data_buf_(buffer), data_size_(buffer)
28  {
29  setp(&data_buf_[0], &data_buf_[0] + data_size_ - 1);
30  }
31 
33  {
34  }
35 
36  void CipherStream::encrypt(std::iostream& stream)
37  {
38  char buf[4096];
39  while (!stream.eof())
40  {
41  std::ios::pos_type pos = stream.tellg();
42 
43  stream.read((char*)&buf, 4096);
44  size_t bytes = stream.gcount();
45 
46  encrypt(buf, bytes);
47 
48  // clear the error flags if we reached the end of the file
49  // but need to write some data
50  if (stream.eof() && (bytes > 0)) stream.clear();
51 
52  stream.seekp(pos, std::ios::beg);
53  stream.write((char*)&buf, bytes);
54  }
55 
56  stream.flush();
57  encrypt_final();
58  }
59 
60  void CipherStream::decrypt(std::iostream& stream)
61  {
62  char buf[4096];
63  while (!stream.eof())
64  {
65  std::ios::pos_type pos = stream.tellg();
66 
67  stream.read((char*)&buf, 4096);
68  size_t bytes = stream.gcount();
69 
70  decrypt(buf, bytes);
71 
72  // clear the error flags if we reached the end of the file
73  // but need to write some data
74  if (stream.eof() && (bytes > 0)) stream.clear();
75 
76  stream.seekp(pos, std::ios::beg);
77  stream.write((char*)&buf, bytes);
78  }
79 
80  stream.flush();
81  decrypt_final();
82  }
83 
85  {
86  int ret = std::char_traits<char>::eq_int_type(this->overflow(
87  std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
88  : 0;
89 
90  // do cipher stuff
91  switch (_mode)
92  {
93  case CIPHER_ENCRYPT:
94  encrypt_final();
95  break;
96 
97  case CIPHER_DECRYPT:
98  decrypt_final();
99  break;
100  }
101 
102  return ret;
103  }
104 
105  std::char_traits<char>::int_type CipherStream::overflow(std::char_traits<char>::int_type c)
106  {
107  char *ibegin = &data_buf_[0];
108  char *iend = pptr();
109 
110  // mark the buffer as free
111  setp(&data_buf_[0], &data_buf_[0] + data_size_ - 1);
112 
113  if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
114  {
115  *iend++ = std::char_traits<char>::to_char_type(c);
116  }
117 
118  // if there is nothing to send, just return
119  if ((iend - ibegin) == 0)
120  {
121  return std::char_traits<char>::not_eof(c);
122  }
123 
124  // do cipher stuff
125  switch (_mode)
126  {
127  case CIPHER_ENCRYPT:
128  encrypt(&data_buf_[0], (iend - ibegin));
129  break;
130 
131  case CIPHER_DECRYPT:
132  decrypt(&data_buf_[0], (iend - ibegin));
133  break;
134  }
135 
136  // write result to stream
137  _stream.write(&data_buf_[0], (iend - ibegin));
138 
139  return std::char_traits<char>::not_eof(c);
140  }
141 }