2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "namespaces.hh"
26 #include "sodcrypto.hh"
34 key
.resize(crypto_secretbox_KEYBYTES
);
36 randombytes_buf(reinterpret_cast<unsigned char*>(&key
.at(0)), key
.size());
38 return "\""+Base64Encode(key
)+"\"";
41 bool sodIsValidKey(const std::string
& key
)
43 return key
.size() == crypto_secretbox_KEYBYTES
;
46 std::string
sodEncryptSym(const std::string
& msg
, const std::string
& key
, SodiumNonce
& nonce
)
48 if (!sodIsValidKey(key
)) {
49 throw std::runtime_error("Invalid encryption key of size " + std::to_string(key
.size()) + ", use setKey() to set a valid key");
52 std::string ciphertext
;
53 ciphertext
.resize(msg
.length() + crypto_secretbox_MACBYTES
);
54 crypto_secretbox_easy(reinterpret_cast<unsigned char*>(&ciphertext
.at(0)),
55 reinterpret_cast<const unsigned char*>(msg
.c_str()),
58 reinterpret_cast<const unsigned char*>(key
.c_str()));
64 std::string
sodDecryptSym(const std::string
& msg
, const std::string
& key
, SodiumNonce
& nonce
)
66 std::string decrypted
;
68 if (msg
.length() < crypto_secretbox_MACBYTES
) {
69 throw std::runtime_error("Could not decrypt message of size " + std::to_string(msg
.length()));
72 if (!sodIsValidKey(key
)) {
73 throw std::runtime_error("Invalid decryption key of size " + std::to_string(key
.size()) + ", use setKey() to set a valid key");
76 decrypted
.resize(msg
.length() - crypto_secretbox_MACBYTES
);
78 if (crypto_secretbox_open_easy(reinterpret_cast<unsigned char*>(const_cast<char *>(decrypted
.data())),
79 reinterpret_cast<const unsigned char*>(msg
.c_str()),
82 reinterpret_cast<const unsigned char*>(key
.c_str())) != 0) {
83 throw std::runtime_error("Could not decrypt message, please check that the key configured with setKey() is correct");
90 std::string
sodEncryptSym(const std::string
& msg
, const std::string
& key
, SodiumNonce
& nonce
)
94 std::string
sodDecryptSym(const std::string
& msg
, const std::string
& key
, SodiumNonce
& nonce
)
101 return "\"plaintext\"";
104 bool sodIsValidKey(const std::string
& key
)
113 #include <inttypes.h>
116 char B64Decode1(char cInChar
)
118 // The incoming character will be A-Z, a-z, 0-9, +, /, or =.
119 // The idea is to quickly determine which grouping the
120 // letter belongs to and return the associated value
121 // without having to search the global encoding string
122 // (the value we're looking for would be the resulting
123 // index into that string).
125 // To do that, we'll play some tricks...
126 unsigned char iIndex
= '\0';
141 // Must be 'A'-'Z', 'a'-'z', '0'-'9', or an error...
143 // Numerically, small letters are "greater" in value than
144 // capital letters and numerals (ASCII value), and capital
145 // letters are "greater" than numerals (again, ASCII value),
146 // so we check for numerals first, then capital letters,
147 // and finally small letters.
148 iIndex
= '9' - cInChar
;
149 if ( iIndex
> 0x3F ) {
150 // Not from '0' to '9'...
151 iIndex
= 'Z' - cInChar
;
152 if ( iIndex
> 0x3F ) {
153 // Not from 'A' to 'Z'...
154 iIndex
= 'z' - cInChar
;
155 if ( iIndex
> 0x3F ) {
156 // Invalid character...cannot
158 iIndex
= 0x80; // set the high bit
162 iIndex
= (('z' - iIndex
) - 'a') + 26;
167 iIndex
= ('Z' - iIndex
) - 'A';
171 // Adjust the index...
172 iIndex
= (('9' - iIndex
) - '0') + 52;
181 inline char B64Encode1(unsigned char uc
)
205 using namespace anonpdns
;
207 int B64Decode(const std::string
& strInput
, std::string
& strOutput
)
209 // Set up a decoding buffer
211 char* pBuf
= (char*)&cBuf
;
213 // Decoding management...
214 int iBitGroup
= 0, iInNum
= 0;
216 // While there are characters to process...
218 // We'll decode characters in blocks of 4, as
219 // there are 4 groups of 6 bits in 3 bytes. The
220 // incoming Base64 character is first decoded, and
221 // then it is inserted into the decode buffer
222 // (with any relevant shifting, as required).
223 // Later, after all 3 bytes have been reconstituted,
224 // we assign them to the output string, ultimately
225 // to be returned as the original message.
226 int iInSize
= strInput
.size();
227 unsigned char cChar
= '\0';
229 while ( iInNum
< iInSize
) {
230 // Fill the decode buffer with 4 groups of 6 bits
233 for ( iBitGroup
= 0; iBitGroup
< 4; ++iBitGroup
) {
234 if ( iInNum
< iInSize
) {
235 // Decode a character
236 if(strInput
.at(iInNum
)=='=')
238 while(isspace(strInput
.at(iInNum
)))
240 cChar
= B64Decode1(strInput
.at(iInNum
++));
244 // Decode a padded zero
248 // Check for valid decode
253 switch ( iBitGroup
) {
255 // The first group is copied into
256 // the least significant 6 bits of
257 // the decode buffer...these 6 bits
258 // will eventually shift over to be
259 // the most significant bits of the
265 // For groupings 1-3, simply shift
266 // the bits in the decode buffer over
267 // by 6 and insert the 6 from the
268 // current decode character.
269 cBuf
= (cBuf
<< 6) | cChar
;
275 // Interpret the resulting 3 bytes...note there
276 // may have been padding, so those padded bytes
277 // are actually ignored.
278 #if BYTE_ORDER == BIG_ENDIAN
279 strOutput
+= pBuf
[sizeof(long)-3];
280 strOutput
+= pBuf
[sizeof(long)-2];
281 strOutput
+= pBuf
[sizeof(long)-1];
283 strOutput
+= pBuf
[2];
284 strOutput
+= pBuf
[1];
285 strOutput
+= pBuf
[0];
289 strOutput
.resize(strOutput
.length()-pad
);
296 Copyright 2001-2002 Randy Charles Morin
297 The Encode static method takes an array of 8-bit values and returns a base-64 stream.
301 std::string
Base64Encode (const std::string
& vby
)
304 if (vby
.size () == 0)
308 for (unsigned int i
= 0; i
< vby
.size (); i
+= 3)
310 unsigned char by1
= 0, by2
= 0, by3
= 0;
312 if (i
+ 1 < vby
.size ())
316 if (i
+ 2 < vby
.size ())
320 unsigned char by4
= 0, by5
= 0, by6
= 0, by7
= 0;
322 by5
= ((by1
& 0x3) << 4) | (by2
>> 4);
323 by6
= ((by2
& 0xf) << 2) | (by3
>> 6);
325 retval
+= B64Encode1 (by4
);
326 retval
+= B64Encode1 (by5
);
327 if (i
+ 1 < vby
.size ())
329 retval
+= B64Encode1 (by6
);
335 if (i
+ 2 < vby
.size ())
337 retval
+= B64Encode1 (by7
);
343 /* if ((i % (76 / 4 * 3)) == 0)