From bd6e6540c2fc394dd8ad1c3de1f82b1665870ff8 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 14 Jun 2002 05:49:34 +0000 Subject: [PATCH] added RSA library svn path=/trunk/boinc/; revision=112 --- checkin_notes | 14 +++++ lib/Makefile.in | 16 ++++- lib/crypt.C | 122 ++++++++++++++++++++++++++++++++++++ lib/crypt.h | 24 +++++++ lib/crypt_prog.C | 100 +++++++++++++++++++++++++++++ notes | 48 ++++++++++++++ sched/file_upload_handler.C | 11 ++++ 7 files changed, 332 insertions(+), 3 deletions(-) create mode 100644 lib/crypt.C create mode 100644 lib/crypt.h create mode 100644 lib/crypt_prog.C create mode 100644 sched/file_upload_handler.C diff --git a/checkin_notes b/checkin_notes index 3828ae4e41..ad1ebb192d 100755 --- a/checkin_notes +++ b/checkin_notes @@ -479,3 +479,17 @@ David A June 9 2002 test_*.php tools/ add.C + +David A June 13 2002 + - added the RSAEuro library to the project, + and some interface routines for it. + + RSAEuro/ (new) + source/* + demo/* + lib/ + crypt.C,h (new) + crypt_prog.C + Makefile.in + sched/ + file_upload_handler.C diff --git a/lib/Makefile.in b/lib/Makefile.in index 0c14728164..5ba976814a 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -7,18 +7,25 @@ VERSION = 1 CFLAGS = -g -CC = @CC@ $(CFLAGS) +CC = @CC@ $(CFLAGS) -I ../RSAEuro/source -PROGS = md5_test shmem_test synch_test +PROGS = md5_test shmem_test synch_test crypt_prog MD5_OBJS = \ md5.o \ md5_file.o +CRYPT_OBJS = \ + crypt.o + +CRYPT_LIBS = \ + $(MD5_OBJS) \ + ../RSAEuro/unix/rsaeuro.a + COUNTRY_OBJS = \ countries.o -all: $(PROGS) $(MD5_OBJS) +all: $(PROGS) $(MD5_OBJS) $(CRYPT_OBJS) .C.o: $(CC) -c -o $*.o $< @@ -34,6 +41,9 @@ shmem_test: shmem_test.o shmem.o synch_test: synch_test.o synch.o $(CC) synch_test.o synch.o -o synch_test +crypt_prog: crypt_prog.o crypt.o + $(CC) crypt_prog.o crypt.o $(CRYPT_LIBS) -o crypt_prog + clean: rm -f *.o $(PROGS) core dependencies diff --git a/lib/crypt.C b/lib/crypt.C new file mode 100644 index 0000000000..0d6b536ef1 --- /dev/null +++ b/lib/crypt.C @@ -0,0 +1,122 @@ +#include +#include + +#include "rsaeuro.h" +extern "C" { +#include "rsa.h" +} +#include "md5_file.h" +#include "crypt.h" + +// print some data in hex notation. +// NOTE: since length may not be known to the reader, +// we follow the data with a non-hex character '.' +// +int print_hex_data(FILE* f, DATA_BLOCK& x) { + int i; + + for (i=0; ibits); + len = size - sizeof(key->bits); + x.data = key->data; + x.len = len; + return print_hex_data(f, x); +} + +int scan_key_hex(FILE* f, KEY* key, int size) { + int len, i; + + fscanf(f, "%d", &key->bits); + len = size - sizeof(key->bits); + for (i=0; idata+i); + } + fscanf(f, "."); + return 0; +} + +// encrypt some data. +// The amount encrypted may be less than what's supplied. +// The output buffer must be at least MIN_OUT_BUFFER_SIZE. +// The output block must be decrypted in its entirety. +// +int encrypt_private( + R_RSA_PRIVATE_KEY& key, DATA_BLOCK& in, DATA_BLOCK& out, + int& nbytes_encrypted +) { + int retval, n; + n = in.len; + if (n >= key.bits-11) { + n = key.bits-11; + } + retval = RSAPrivateEncrypt(out.data, &out.len, in.data, n, &key); + if (retval) return retval; + nbytes_encrypted = n; + return 0; +} + +int decrypt_public(R_RSA_PUBLIC_KEY& key, DATA_BLOCK& in, DATA_BLOCK& out) { + RSAPublicDecrypt(out.data, &out.len, in.data, in.len, &key); +} + +int sign_file(char* path, R_RSA_PRIVATE_KEY& key, DATA_BLOCK& signature) { + char md5_buf[64]; + double file_length; + DATA_BLOCK in_block; + int retval, n; + + retval = md5_file(path, md5_buf, file_length); + if (retval) return retval; + in_block.data = (unsigned char*)md5_buf; + in_block.len = strlen(md5_buf); + retval = encrypt_private(key, in_block, signature, n); + if (retval) return retval; + return 0; +} + +int verify_file( + char* path, R_RSA_PUBLIC_KEY& key, DATA_BLOCK& signature, bool& answer +) { + char md5_buf[64], clear_buf[256]; + double file_length; + int n, retval; + DATA_BLOCK clear_signature; + + retval = md5_file(path, md5_buf, file_length); + if (retval) return retval; + n = strlen(md5_buf); + clear_signature.data = (unsigned char*)clear_buf; + clear_signature.len = 256; + retval = decrypt_public(key, signature, clear_signature); + if (retval) return retval; + answer = !strncmp(md5_buf, clear_buf, n); + return 0; +} diff --git a/lib/crypt.h b/lib/crypt.h new file mode 100644 index 0000000000..d935fc6543 --- /dev/null +++ b/lib/crypt.h @@ -0,0 +1,24 @@ +// some interface functions for RSAEuro + +struct KEY { + unsigned short int bits; + unsigned char data[1]; +}; + +struct DATA_BLOCK { + unsigned char* data; + unsigned int len; +}; + +#define MIN_OUT_BUFFER_SIZE MAX_RSA_MODULUS_LEN+1 + +int print_hex_data(FILE* f, DATA_BLOCK&); +int scan_hex_data(FILE* f, DATA_BLOCK&); +int print_key_hex(FILE*, KEY* key, int len); +int scan_key_hex(FILE*, KEY* key, int len); +int encrypt_private( + R_RSA_PRIVATE_KEY& key, DATA_BLOCK& in, DATA_BLOCK& out, int& +); +int decrypt_public(R_RSA_PUBLIC_KEY& key, DATA_BLOCK& in, DATA_BLOCK& out); +int sign_file(char* path, R_RSA_PRIVATE_KEY&, DATA_BLOCK& signature); +int verify_file(char* path, R_RSA_PUBLIC_KEY&, DATA_BLOCK& signature, bool&); diff --git a/lib/crypt_prog.C b/lib/crypt_prog.C new file mode 100644 index 0000000000..b2fe4e22c2 --- /dev/null +++ b/lib/crypt_prog.C @@ -0,0 +1,100 @@ +// utility program for encryption. +// +// -genkey n private_keyfile public_keyfile +// create a key pair with n bits (512 <= n <= 2048) +// write it in hex notation +// -sign file private_keyfile +// create a signature for a given file +// write it in hex notation +// -verify file signature_file public_keyfile +// verify a signature +// -crypt_test private_keyfile public_keyfile +// test encrypt/decrypt + +#include +#include + +#include "rsaeuro.h" + +#include "crypt.h" + +void die(char* p) { + fputs(p, stderr); + exit(1); +} + +main(int argc, char** argv) { + R_RANDOM_STRUCT randomStruct; + R_RSA_PUBLIC_KEY public_key; + R_RSA_PRIVATE_KEY private_key; + R_RSA_PROTO_KEY protoKey; + int n, retval; + bool is_valid; + DATA_BLOCK signature, in, out; + unsigned char signature_buf[256], buf[256], buf2[256]; + FILE *f, *fpriv, *fpub; + + if (argc == 1) { + printf("missing command\n"); + exit(1); + } + if (!strcmp(argv[1], "-genkey")) { + n = atoi(argv[2]); + + R_RandomCreate(&randomStruct); + + protoKey.bits = n; + protoKey.useFermat4 = 1; + retval = R_GeneratePEMKeys( + &public_key, &private_key, &protoKey, &randomStruct + ); + if (retval) die("R_GeneratePEMKeys\n"); + + fpriv = fopen(argv[3], "w"); + if (!fpriv) die("fopen"); + fpub = fopen(argv[4], "w"); + if (!fpub) die("fopen"); + print_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key)); + print_key_hex(fpub, (KEY*)&public_key, sizeof(public_key)); + } else if (!strcmp(argv[1], "-sign")) { + fpriv = fopen(argv[3], "r"); + if (!fpriv) die("fopen"); + retval = scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key)); + if (retval) die("scan_key_hex\n"); + signature.data = signature_buf; + signature.len = 256; + retval = sign_file(argv[2], private_key, signature); + print_hex_data(stdout, signature); + } else if (!strcmp(argv[1], "-verify")) { + fpub = fopen(argv[4], "r"); + if (!fpub) die("fopen"); + retval = scan_key_hex(fpub, (KEY*)&public_key, sizeof(public_key)); + if (retval) die("read_public_key"); + f = fopen(argv[3], "r"); + signature.data = signature_buf; + signature.len = 256; + retval = scan_hex_data(f, signature); + if (retval) die("scan_hex_data"); + retval = verify_file(argv[2], public_key, signature, is_valid); + if (retval) die("verify_file"); + printf("file is %s\n", is_valid?"valid":"invalid"); + } else if (!strcmp(argv[1], "-test_crypt")) { + fpriv = fopen(argv[2], "r"); + if (!fpriv) die("fopen"); + retval = scan_key_hex(fpriv, (KEY*)&private_key, sizeof(private_key)); + if (retval) die("scan_key_hex\n"); + fpub = fopen(argv[3], "r"); + if (!fpub) die("fopen"); + retval = scan_key_hex(fpub, (KEY*)&public_key, sizeof(public_key)); + if (retval) die("read_public_key"); + in.data = (unsigned char*) "foobar"; + in.len = strlen((char*)in.data); + out.data = buf; + encrypt_private(private_key, in, out, n); + in = out; + out.data = buf2; + decrypt_public(public_key, in, out); + } else { + printf("unrecognized command\n"); + } +} diff --git a/notes b/notes index 47e64b9448..f83d4dbe8d 100644 --- a/notes +++ b/notes @@ -235,3 +235,51 @@ Core/App connection percent done I just checkpointed CPU time so far +------------------- +File upload security +Each project has a "file upload key pair" +Scheduling server has private key; +data servers have public key. +The key pair may be changed periodically; +data servers have to store old and new during transitions + +- in DB, result XML has format + + + 123123 + + ... + + +- RPC reply: result XML info has format + + + ... + ... (added by server) + + + foo + ... (digital signature of element; added by server) + + +- Client stores: + for each result (in state file, in memory) + exact text of tag + signature + +- On file upload, client sends + element (exact text) + + ... + + blah + 123 + 1234 + + ... data + +- file upload handler does: + parse header (up to ) + validate signature of + verify that filename is in list of file_infos + verify that total size is within limit diff --git a/sched/file_upload_handler.C b/sched/file_upload_handler.C new file mode 100644 index 0000000000..4854ad46aa --- /dev/null +++ b/sched/file_upload_handler.C @@ -0,0 +1,11 @@ +// The input to this program looks like this: +// +// +// ... +// ... +// +// ... +// +// +// blah +// ... (data)