Skip to content

Commit

Permalink
libcouchbase: add FLE example
Browse files Browse the repository at this point in the history
  • Loading branch information
avsej committed Jun 25, 2018
1 parent 6e938f3 commit c3a7661
Show file tree
Hide file tree
Showing 13 changed files with 1,115 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ PHP

An example of Symmetric Key encryption using AES-256 and SHA256 signing to encrypt fields within a document.

C |
[C](c/encryption/openssl_symmetric_provider.c) |
Python |
[.NET](dotnet/FieldEncryptionAes.cs) |
Go |
Expand All @@ -368,7 +368,7 @@ Java |

An example of field field encryption using the Asymmetric Key RSA-2048 algorithm and OAEP-SHA1 padding.

C |
[C](c/encryption/openssl_asymmetric_provider.c) |
Python |
[.NET](dotnet/FieldEncryptionRsa.cs) |
Go |
Expand Down
4 changes: 4 additions & 0 deletions c/encryption/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
openssl_asymmetric_decrypt
openssl_asymmetric_encrypt
openssl_symmetric_decrypt
openssl_symmetric_encrypt
21 changes: 21 additions & 0 deletions c/encryption/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
LDFLAGS=-lcouchbase -lm
CFLAGS=-g

OPENSSL_LDFLAGS=$(shell pkg-config --libs openssl) ${LDFLAGS}
OPENSSL_CFLAGS=$(shell pkg-config --cflags openssl) ${CFLAGS}

all: openssl_symmetric_encrypt openssl_symmetric_decrypt \
openssl_asymmetric_encrypt openssl_asymmetric_decrypt

openssl_symmetric_encrypt: openssl_symmetric_encrypt.c openssl_symmetric_provider.c common_provider.c
${CC} ${OPENSSL_CFLAGS} ${OPENSSL_LDFLAGS} -o $@ $^

openssl_symmetric_decrypt: openssl_symmetric_decrypt.c openssl_symmetric_provider.c common_provider.c
${CC} ${OPENSSL_CFLAGS} ${OPENSSL_LDFLAGS} -o $@ $^


openssl_asymmetric_encrypt: openssl_asymmetric_encrypt.c openssl_asymmetric_provider.c common_provider.c
${CC} ${OPENSSL_CFLAGS} ${OPENSSL_LDFLAGS} -o $@ $^

openssl_asymmetric_decrypt: openssl_asymmetric_decrypt.c openssl_asymmetric_provider.c common_provider.c
${CC} ${OPENSSL_CFLAGS} ${OPENSSL_LDFLAGS} -o $@ $^
76 changes: 76 additions & 0 deletions c/encryption/common_provider.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2018 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "common_provider.h"

/**
*
*
* ¡DO NOT REUSE THESE KEYS. THEY HERE TO SIMPLIFY EXAMPLES!
*
* ¡REAL APPLICATION SHOULD IMPLEMENT SECURE KEY PROVIDERS!
*
*/

char *common_aes256_key_id = "mykeyid";

uint8_t *common_hmac_sha256_key = "myauthpassword";

uint8_t common_aes256_key[AES256_KEY_SIZE] = "!mysecretkey#9^5usdk39d&dlf)03sL";
uint8_t common_aes256_iv[AES256_IV_SIZE] = {0x65, 0xe7, 0x66, 0xbe, 0x35, 0xb2, 0xd2, 0x52,
0x2b, 0x2e, 0x7e, 0x8e, 0x99, 0x9, 0x8d, 0xa9};

char *common_rsa_private_key_id = "MyPrivateKeyName";
char *common_rsa_public_key_id = "MyPublicKeyName";

char *common_rsa_private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIIEpAIBAAKCAQEAwP6s/siq+geZAcN858as1U6VIFeNDjvepl88jyd748idDt1a\n"
"hDqw7pGw5WMygq04anWQG3kKUUhElxwG9BJ/z4rxJXO0Vbflv0whgBlTVVxXuXSP\n"
"wtyA200CENLO6aTaVN/aettSvA3cEuTit6eg4Ayi0iSO97SI/9Jp4XeI4bA5Ls55\n"
"1Y9XR+PVbnaNgDWxGvebpw9GvjeK/hUdMHwP8QhLdyLLjbQ6i3YxOWFYWqjtSQav\n"
"CdkpHNui7U1rULxYYFSAhR64dOwoTs2yB8lLMQsjTdIQR6oQZgaKRlVzPzHlJgp0\n"
"tISJxvJYXrct7ZEjEFtTLnOMx4E7MbmcN3bsDwIDAQABAoIBAGiiq5CHo4tjyyUV\n"
"pAbVxKbxsBCU5zksZI63W9IRii35eo2wnX7Lg1oVS19S5PPMjqXJj5QVj+55zBZR\n"
"b8Oss/cGUbAIh2FiDwIkeJVHJdNF+ZnnBHqVqpc7rT8JzH0IkAcsRvwNJVIoAYWM\n"
"6w6/p41RzIU6pPjPvOdWYWmIsYIKZAhVnTf8QXDBpBdjzrrlTnocChNtEdkqyCFm\n"
"FILOWUiFbzWsHJe5/1o+v+Kw4qQGHNZVpFi2vQCJxTLdEbcUHCmVqgQOs+1hs+Ax\n"
"37pkXfVBRh97E5RV0Os8JtH3smw9uCcQveJanmuPVhsa+8zjOK2j1AHjdsaPZgMP\n"
"wuleVoECgYEA5mJ72lPRcFjNTTDQfLUHxCq4rWekkS+QsgPyBuE8z5mi7SsHuScV\n"
"i+PcLehRY8e6Z464Kl9Ni6c17HcM+Bm8ay70hxPeTlqrVBjxKiTixF1BccbBHPjd\n"
"Jl0WCEODxKMp5TAasJsfM7Pg18cYNakmOqK/agc7LJtsyo99jKfFYR8CgYEA1nPz\n"
"mGfhZZ2JXsNBNlqyvitV7Uzwa62DMGJUuosODnaz5v4gTPZhMF4gaOwh3wofP882\n"
"JZM1YEDF64Nn3tMDXImidoE9tKDMPyT1+obaBEPe8AfhAJGfMrWHgU3Yicd16bxK\n"
"vbU3kODpFgBtnE50JcceEyFYTWzZeNRWlsW4ZxECgYEAqTxDGthji5HQDhoDrPgW\n"
"omV3j/oIi5ZTRlFbou4mC6IiavInFD2/uClD/n0f/JolNhlC8+1aO3IzTGcPodjV\n"
"7i5p9igEL66vGHHSBlFeOzz97CRCi5PMcHgEzUE7NGFfTzqNAJqSyxoh2qAoCpMc\n"
"wAn5blutflEWE55gbch4V6UCgYEArFiBU2FgzmZd6O9ocENR1O1E4DHuIctPXEoa\n"
"J9TrFgqlqCVhVhjHoLR0vX3P9szOslxX+riks9c6eHyhtHzG/c6K50wUiB6WJsUQ\n"
"fidz/OuCtkrOs8NUOs+SuAMU3B2VkKPHOVDy+BcYm5r6fBy80UOF0wAAVDD/UVDs\n"
"ybza5tECgYB+ksZiUbZ+8WTXVIB3HJJT8U8bZ8676lrRUJ5YxB+avHh4g/TI+e53\n"
"jZKBVvB3Mhp6QFMZITuUTRgiGuAjBap4SZ32Pmyu3TxiWDxKktmvFMPLUVFntDJ0\n"
"th2u9Xpw8+T01AOCFc0PKtC8g0Covxu+qWLfqnJnTCx+Q03+dQj9rQ==\n"
"-----END RSA PRIVATE KEY-----\n";

char *common_rsa_public_key = "-----BEGIN PUBLIC KEY-----\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwP6s/siq+geZAcN858as\n"
"1U6VIFeNDjvepl88jyd748idDt1ahDqw7pGw5WMygq04anWQG3kKUUhElxwG9BJ/\n"
"z4rxJXO0Vbflv0whgBlTVVxXuXSPwtyA200CENLO6aTaVN/aettSvA3cEuTit6eg\n"
"4Ayi0iSO97SI/9Jp4XeI4bA5Ls551Y9XR+PVbnaNgDWxGvebpw9GvjeK/hUdMHwP\n"
"8QhLdyLLjbQ6i3YxOWFYWqjtSQavCdkpHNui7U1rULxYYFSAhR64dOwoTs2yB8lL\n"
"MQsjTdIQR6oQZgaKRlVzPzHlJgp0tISJxvJYXrct7ZEjEFtTLnOMx4E7MbmcN3bs\n"
"DwIDAQAB\n"
"-----END PUBLIC KEY-----\n";
39 changes: 39 additions & 0 deletions c/encryption/common_provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2018 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef _COMMON_PROVIDER_H
#define _COMMON_PROVIDER_H

#include <libcouchbase/couchbase.h>

extern char * common_aes256_key_id;

#define AES256_KEY_SIZE 32
#define AES256_IV_SIZE 16

extern uint8_t common_aes256_key[AES256_KEY_SIZE];
extern uint8_t common_aes256_iv[AES256_IV_SIZE];

extern uint8_t *common_hmac_sha256_key;

extern char *common_rsa_private_key;
extern char *common_rsa_public_key;

extern char *common_rsa_private_key_id;
extern char *common_rsa_public_key_id;

#endif
134 changes: 134 additions & 0 deletions c/encryption/openssl_asymmetric_decrypt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2018 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdio.h>
#include <libcouchbase/couchbase.h>
#include <libcouchbase/crypto.h>
#include <stdlib.h>
#include <string.h> /* strlen */
#ifdef _WIN32
#define PRIx64 "I64x"
#else
#include <inttypes.h>
#endif

#include "openssl_asymmetric_provider.h"

static void die(lcb_t instance, const char *msg, lcb_error_t err)
{
fprintf(stderr, "%s. Received code 0x%X (%s)\n", msg, err, lcb_strerror(instance, err));
exit(EXIT_FAILURE);
}

static void op_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
{
if (rb->rc == LCB_SUCCESS) {
const lcb_RESPGET *rg = (const lcb_RESPGET *)rb;
lcbcrypto_CMDDECRYPT dcmd = {};
lcbcrypto_FIELDSPEC field = {};
lcb_error_t err;

printf("VALUE: %.*s\n", (int)rg->nvalue, rg->value);
dcmd.version = 0;
dcmd.prefix = NULL;
dcmd.doc = rg->value;
dcmd.ndoc = rg->nvalue;
dcmd.out = NULL;
dcmd.nout = 0;
dcmd.nfields = 1;
dcmd.fields = &field;
field.name = "message";
field.alg = "RSA-2048-OAEP-SHA1";
err = lcbcrypto_decrypt_fields(instance, &dcmd);
if (err != LCB_SUCCESS) {
die(instance, "Couldn't decrypt field 'message'", err);
}
if (dcmd.out == NULL) {
die(instance, "Crypto provider returned success, but document is NULL", LCB_EINVAL);
}
/* chop trailing LF for nicer look */
if (dcmd.out[dcmd.nout - 1] == '\n') {
dcmd.out[dcmd.nout - 1] = ' ';
}
printf("PLAIN: %.*s\n", (int)dcmd.nout, dcmd.out);
free(dcmd.out); // NOTE: it should be compatible with what providers use to allocate memory
printf("CAS: 0x%" PRIx64 "\n", rb->cas);
} else {
die(instance, lcb_strcbtype(cbtype), rb->rc);
}
}

static void get_encrypted(lcb_t instance, const char *key)
{
lcb_CMDGET cmd = {};
lcb_error_t err;
LCB_CMD_SET_KEY(&cmd, key, strlen(key));
printf("KEY: %s\n", key);
err = lcb_get3(instance, NULL, &cmd);
if (err != LCB_SUCCESS) {
die(instance, "Couldn't schedule get operation", err);
}
lcb_wait(instance);
}

int main(int argc, char *argv[])
{
lcb_error_t err;
lcb_t instance;

{
struct lcb_create_st create_options = {};
create_options.version = 3;
create_options.v.v3.connstr = "couchbase://localhost/default";
create_options.v.v3.username = "Administrator";
create_options.v.v3.passwd = "password";

err = lcb_create(&instance, &create_options);
if (err != LCB_SUCCESS) {
die(NULL, "Couldn't create couchbase handle", err);
}

err = lcb_connect(instance);
if (err != LCB_SUCCESS) {
die(instance, "Couldn't schedule connection", err);
}

lcb_wait(instance);

err = lcb_get_bootstrap_status(instance);
if (err != LCB_SUCCESS) {
die(instance, "Couldn't bootstrap from cluster", err);
}

lcb_install_callback3(instance, LCB_CALLBACK_GET, op_callback);
}

lcbcrypto_register(instance, "RSA-2048-OAEP-SHA1", oap_create());

get_encrypted(instance, "secret-1");
printf("\n");
get_encrypted(instance, "secret-2");
printf("\n");
get_encrypted(instance, "secret-3");
printf("\n");
get_encrypted(instance, "secret-4");
printf("\n");
get_encrypted(instance, "secret-5");

lcb_destroy(instance);
return 0;
}
Loading

0 comments on commit c3a7661

Please sign in to comment.