39 #include <openssl/rand.h>
60 static std::string
encryptStringGpg(std::string& user, std::basic_string<unsigned char>
const& input) {
62 gpgme_error_t err = gpgme_new(&ctx);
64 throw BagException((boost::format(
"Failed to create a GPG context: %1%") % gpgme_strerror(err)).str());
67 gpgme_key_t keys[2] = {NULL, NULL};
69 if (user == std::string(
"*")) {
70 user = std::string(keys[0]->uids->name);
73 gpgme_data_t input_data;
74 err = gpgme_data_new_from_mem(&input_data,
reinterpret_cast<const char*
>(input.c_str()), input.length(), 1);
78 (boost::format(
"Failed to encrypt string: gpgme_data_new_from_mem returned %1%") % gpgme_strerror(err)).str());
80 gpgme_data_t output_data;
81 err = gpgme_data_new(&output_data);
83 gpgme_data_release(input_data);
86 (boost::format(
"Failed to encrypt string: gpgme_data_new returned %1%") % gpgme_strerror(err)).str());
88 err = gpgme_op_encrypt(ctx, keys,
static_cast<gpgme_encrypt_flags_t
>(GPGME_ENCRYPT_ALWAYS_TRUST), input_data, output_data);
90 gpgme_data_release(output_data);
91 gpgme_data_release(input_data);
93 throw BagException((boost::format(
"Failed to encrypt: %1%. Have you installed a public key %2%?") % gpgme_strerror(err) % user).str());
95 gpgme_key_release(keys[0]);
96 std::size_t output_length = gpgme_data_seek(output_data, 0, SEEK_END);
97 std::string output(output_length, 0);
98 gpgme_data_seek(output_data, 0, SEEK_SET);
99 ssize_t bytes_read = gpgme_data_read(output_data, &output[0], output_length);
101 gpgme_data_release(output_data);
102 gpgme_data_release(input_data);
104 if (-1 == bytes_read) {
105 throw BagException(
"Failed to read encrypted string");
118 static std::basic_string<unsigned char>
decryptStringGpg(std::string
const& user, std::string
const& input) {
120 gpgme_error_t err = gpgme_new(&ctx);
122 throw BagException((boost::format(
"Failed to create a GPG context: %1%") % gpgme_strerror(err)).str());
125 gpgme_data_t input_data;
126 err = gpgme_data_new_from_mem(&input_data, input.c_str(), input.length(), 1);
130 (boost::format(
"Failed to decrypt bag: gpgme_data_new_from_mem returned %1%") % gpgme_strerror(err)).str());
132 gpgme_data_t output_data;
133 err = gpgme_data_new(&output_data);
135 gpgme_data_release(input_data);
138 (boost::format(
"Failed to decrypt bag: gpgme_data_new returned %1%") % gpgme_strerror(err)).str());
140 err = gpgme_op_decrypt(ctx, input_data, output_data);
142 gpgme_data_release(output_data);
143 gpgme_data_release(input_data);
145 throw BagException((boost::format(
"Failed to decrypt bag: %1%. Have you installed a private key %2%?") % gpgme_strerror(err) % user).str());
147 std::size_t output_length = gpgme_data_seek(output_data, 0, SEEK_END);
148 if (output_length != AES_BLOCK_SIZE) {
149 gpgme_data_release(output_data);
150 gpgme_data_release(input_data);
152 throw BagException(
"Decrypted string length mismatches");
154 std::basic_string<unsigned char> output(output_length, 0);
155 gpgme_data_seek(output_data, 0, SEEK_SET);
156 ssize_t bytes_read = gpgme_data_read(output_data,
reinterpret_cast<char*
>(&output[0]), output_length);
158 gpgme_data_release(output_data);
159 gpgme_data_release(input_data);
161 if (-1 == bytes_read) {
162 throw BagException(
"Failed to read decrypted symmetric key");
168 ros::M_string::const_iterator it = header_fields.find(field_name);
169 if (it == header_fields.end()) {
170 return std::string();
192 (boost::format(
"Encryption user has already been set to %s") %
gpg_key_user_.c_str()).str());
198 std::basic_string<unsigned char> compressed_chunk(chunk_size, 0);
199 file.seek(chunk_data_pos);
200 file.read((
char*) &compressed_chunk[0], chunk_size);
202 std::size_t pad_size = AES_BLOCK_SIZE - chunk_size % AES_BLOCK_SIZE;
203 compressed_chunk.resize(compressed_chunk.length() + pad_size, pad_size);
205 std::basic_string<unsigned char> encrypted_chunk(compressed_chunk.length(), 0);
206 std::basic_string<unsigned char> iv(AES_BLOCK_SIZE, 0);
207 if (!RAND_bytes(&iv[0], AES_BLOCK_SIZE)) {
208 throw BagException(
"Failed to build initialization vector");
210 file.seek(chunk_data_pos);
211 file.write((
char*) &iv[0], AES_BLOCK_SIZE);
212 AES_cbc_encrypt(&compressed_chunk[0], &encrypted_chunk[0], encrypted_chunk.length(), &
aes_encrypt_key_, &iv[0], AES_ENCRYPT);
214 file.write((
char*) &encrypted_chunk[0], encrypted_chunk.length());
215 file.truncate(chunk_data_pos + AES_BLOCK_SIZE + encrypted_chunk.length());
216 return AES_BLOCK_SIZE + encrypted_chunk.length();
221 if (chunk_header.compressed_size % AES_BLOCK_SIZE != 0) {
222 throw BagFormatException((boost::format(
"Error in encrypted chunk size: %d") % chunk_header.compressed_size).str());
225 if (chunk_header.compressed_size < AES_BLOCK_SIZE) {
226 throw BagFormatException((boost::format(
"No initialization vector in encrypted chunk: %d") % chunk_header.compressed_size).str());
228 std::basic_string<unsigned char> iv(AES_BLOCK_SIZE, 0);
229 file.read((
char*) &iv[0], AES_BLOCK_SIZE);
230 std::basic_string<unsigned char> encrypted_chunk(chunk_header.compressed_size - AES_BLOCK_SIZE, 0);
231 file.read((
char*) &encrypted_chunk[0], chunk_header.compressed_size - AES_BLOCK_SIZE);
233 decrypted_chunk.setSize(chunk_header.compressed_size - AES_BLOCK_SIZE);
234 AES_cbc_encrypt(&encrypted_chunk[0], (
unsigned char*) decrypted_chunk.getData(), chunk_header.compressed_size - AES_BLOCK_SIZE,
236 if (decrypted_chunk.getSize() == 0) {
239 decrypted_chunk.setSize(decrypted_chunk.getSize() - *(decrypted_chunk.getData()+decrypted_chunk.getSize()-1));
266 std::size_t pad_size = AES_BLOCK_SIZE - header_len % AES_BLOCK_SIZE;
267 uint32_t encrypted_buffer_size = header_len + pad_size;
268 std::basic_string<unsigned char> header_buffer_with_pad(encrypted_buffer_size, pad_size);
269 memcpy(&header_buffer_with_pad[0], header_buffer.get(), header_len);
271 std::basic_string<unsigned char> encrypted_buffer(encrypted_buffer_size, 0);
272 std::basic_string<unsigned char> iv(AES_BLOCK_SIZE, 0);
273 if (!RAND_bytes(&iv[0], AES_BLOCK_SIZE)) {
276 encrypted_buffer_size += AES_BLOCK_SIZE;
277 file.write((
char*) &encrypted_buffer_size, 4);
278 encrypted_buffer_size -= AES_BLOCK_SIZE;
279 file.write((
char*) &iv[0], AES_BLOCK_SIZE);
280 AES_cbc_encrypt(&header_buffer_with_pad[0], &encrypted_buffer[0], encrypted_buffer_size, &
aes_encrypt_key_, &iv[0], AES_ENCRYPT);
282 file.write((
char*) &encrypted_buffer[0], encrypted_buffer_size);
287 uint32_t encrypted_header_len;
288 file.
read((
char*) &encrypted_header_len, 4);
289 if (encrypted_header_len % AES_BLOCK_SIZE != 0) {
290 throw BagFormatException((boost::format(
"Error in encrypted header length: %d") % encrypted_header_len).str());
292 if (encrypted_header_len < AES_BLOCK_SIZE) {
293 throw BagFormatException((boost::format(
"No initialization vector in encrypted header: %d") % encrypted_header_len).str());
296 std::basic_string<unsigned char> iv(AES_BLOCK_SIZE, 0);
297 file.
read((
char*) &iv[0], AES_BLOCK_SIZE);
298 encrypted_header_len -= AES_BLOCK_SIZE;
299 std::basic_string<unsigned char> encrypted_header(encrypted_header_len, 0);
300 file.
read((
char*) &encrypted_header[0], encrypted_header_len);
302 header_buffer.
setSize(encrypted_header_len);
303 AES_cbc_encrypt(&encrypted_header[0], (
unsigned char*) header_buffer.
getData(), encrypted_header_len, &
aes_decrypt_key_, &iv[0], AES_DECRYPT);
304 if (header_buffer.
getSize() == 0) {
309 std::string error_msg;