Implementation for a simple order-preserving encryption scheme.

This is meant for use when encrypting the current time within the
period in order to get a monotonically increasing revision counter
without actually revealing our view of the time.

This scheme is far from the most state-of-the-art: don't use it for
anything else without careful analysis by somebody much smarter than
I am.

See ticket #25552 for some rationale for this logic.
This commit is contained in:
Nick Mathewson
2018-05-10 08:46:36 -04:00
parent 860b9a9918
commit 3a45f6ffe9
8 changed files with 407 additions and 0 deletions
+1
View File
@@ -117,6 +117,7 @@ src_test_test_SOURCES += \
src/test/test_controller.c \
src/test/test_controller_events.c \
src/test/test_crypto.c \
src/test/test_crypto_ope.c \
src/test/test_crypto_openssl.c \
src/test/test_data.c \
src/test/test_dir.c \
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/python3
# Copyright 2018, The Tor Project, Inc. See LICENSE for licensing info.
# Reference implementation for our rudimentary OPE code, used to
# generate test vectors. See crypto_ope.c for more details.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.backends import default_backend
from binascii import a2b_hex
#randomly generated and values.
KEY = a2b_hex(
"19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe")
PTS = [ 121132, 82283, 72661, 72941, 123122, 12154, 121574, 11391, 65845,
86301, 61284, 70505, 30438, 60150, 114800, 109403, 21893, 123569,
95617, 48561, 53334, 92746, 7110, 9612, 106958, 46889, 87790, 68878,
47917, 121128, 108602, 28217, 69498, 63870, 57542, 122148, 46254,
42850, 92661, 57720]
IV = b'\x00' * 16
backend = default_backend()
def words():
cipher = Cipher(algorithms.AES(KEY), modes.CTR(IV), backend=backend)
e = cipher.encryptor()
while True:
v = e.update(b'\x00\x00')
yield v[0] + 256 * v[1] + 1
def encrypt(n):
return sum(w for w, _ in zip(words(), range(n)))
def example(n):
return ' {{ {}, UINT64_C({}) }},'.format(n, encrypt(n))
for v in PTS:
print(example(v))
+1
View File
@@ -861,6 +861,7 @@ struct testgroup_t testgroups[] = {
{ "control/", controller_tests },
{ "control/event/", controller_event_tests },
{ "crypto/", crypto_tests },
{ "crypto/ope/", crypto_ope_tests },
{ "crypto/openssl/", crypto_openssl_tests },
{ "dir/", dir_tests },
{ "dir_handle_get/", dir_handle_get_tests },
+1
View File
@@ -212,6 +212,7 @@ extern struct testcase_t container_tests[];
extern struct testcase_t controller_tests[];
extern struct testcase_t controller_event_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t crypto_ope_tests[];
extern struct testcase_t crypto_openssl_tests[];
extern struct testcase_t dir_tests[];
extern struct testcase_t dir_handle_get_tests[];
+148
View File
@@ -0,0 +1,148 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CRYPTO_OPE_PRIVATE
#include "lib/crypt_ops/crypto_ope.h"
#include "common/util_format.h"
#include "test/test.h"
static void
test_crypto_ope_consistency(void *arg)
{
(void)arg;
crypto_ope_t *ope = NULL;
crypto_cipher_t *aes = NULL;
const int TEST_VALS[] = { 5, 500, 1023, 1024, 1025, 2046, 2047, 2048, 2049,
10000, OPE_INPUT_MAX };
unsigned i;
const uint8_t key[32] = "A fixed key, chosen arbitrarily.";
ope = crypto_ope_new(key);
tt_assert(ope);
uint64_t last_val = 0;
for (i = 0; i < ARRAY_LENGTH(TEST_VALS); ++i) {
aes = ope_get_cipher(ope, 0);
int val = TEST_VALS[i];
uint64_t v1 = crypto_ope_encrypt(ope, val);
uint64_t v2 = sum_values_from_cipher(aes, val);
tt_u64_op(v1, OP_EQ, v2);
tt_u64_op(v2, OP_GT, last_val);
last_val = v2;
crypto_cipher_free(aes);
}
done:
crypto_cipher_free(aes);
crypto_ope_free(ope);
}
static void
test_crypto_ope_oob(void *arg)
{
(void)arg;
crypto_ope_t *ope = NULL;
const uint8_t key[32] = "A fixed key, chosen arbitrarily.";
ope = crypto_ope_new(key);
tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MIN));
tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,-100));
tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,0));
tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,1));
tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,7000));
tt_u64_op(UINT64_MAX, OP_NE, crypto_ope_encrypt(ope,OPE_INPUT_MAX));
tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,OPE_INPUT_MAX+1));
tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MAX));
done:
crypto_ope_free(ope);
}
static const char OPE_TEST_KEY[] =
"19e05891d55232c08c2cad91d612fdb9cbd6691949a0742434a76c80bc6992fe";
/* generated by a separate python implementation. */
static const struct {
int v;
uint64_t r;
} OPE_TEST_VECTORS[] = {
{ 121132, UINT64_C(3971694514) },
{ 82283, UINT64_C(2695743564) },
{ 72661, UINT64_C(2381548866) },
{ 72941, UINT64_C(2390408421) },
{ 123122, UINT64_C(4036781069) },
{ 12154, UINT64_C(402067100) },
{ 121574, UINT64_C(3986197593) },
{ 11391, UINT64_C(376696838) },
{ 65845, UINT64_C(2161801517) },
{ 86301, UINT64_C(2828270975) },
{ 61284, UINT64_C(2013616892) },
{ 70505, UINT64_C(2313368870) },
{ 30438, UINT64_C(1001394664) },
{ 60150, UINT64_C(1977329668) },
{ 114800, UINT64_C(3764946628) },
{ 109403, UINT64_C(3585352477) },
{ 21893, UINT64_C(721388468) },
{ 123569, UINT64_C(4051780471) },
{ 95617, UINT64_C(3134921876) },
{ 48561, UINT64_C(1597596985) },
{ 53334, UINT64_C(1753691710) },
{ 92746, UINT64_C(3040874493) },
{ 7110, UINT64_C(234966492) },
{ 9612, UINT64_C(318326551) },
{ 106958, UINT64_C(3506124249) },
{ 46889, UINT64_C(1542219146) },
{ 87790, UINT64_C(2877361609) },
{ 68878, UINT64_C(2260369112) },
{ 47917, UINT64_C(1576681737) },
{ 121128, UINT64_C(3971553290) },
{ 108602, UINT64_C(3559176081) },
{ 28217, UINT64_C(929692460) },
{ 69498, UINT64_C(2280554161) },
{ 63870, UINT64_C(2098322675) },
{ 57542, UINT64_C(1891698992) },
{ 122148, UINT64_C(4004515805) },
{ 46254, UINT64_C(1521227949) },
{ 42850, UINT64_C(1408996941) },
{ 92661, UINT64_C(3037901517) },
{ 57720, UINT64_C(1897369989) },
};
static void
test_crypto_ope_vectors(void *arg)
{
(void)arg;
uint8_t key[32];
crypto_ope_t *ope = NULL, *ope2 = NULL;
base16_decode((char*)key, 32, OPE_TEST_KEY, strlen(OPE_TEST_KEY));
ope = crypto_ope_new(key);
key[8] += 1;
ope2 = crypto_ope_new(key);
unsigned i;
for (i = 0; i < ARRAY_LENGTH(OPE_TEST_VECTORS); ++i) {
int val = OPE_TEST_VECTORS[i].v;
uint64_t res = OPE_TEST_VECTORS[i].r;
tt_u64_op(crypto_ope_encrypt(ope, val), OP_EQ, res);
tt_u64_op(crypto_ope_encrypt(ope2, val), OP_NE, res);
}
done:
crypto_ope_free(ope);
crypto_ope_free(ope2);
}
struct testcase_t crypto_ope_tests[] = {
{ "consistency", test_crypto_ope_consistency, 0, NULL, NULL },
{ "oob", test_crypto_ope_oob, 0, NULL, NULL },
{ "vectors", test_crypto_ope_vectors, 0, NULL, NULL },
END_OF_TESTCASES
};