mirror of https://github.com/BOINC/boinc.git
parent
88f05d8a3e
commit
bd6e6540c2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#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; i<x.len; i++) {
|
||||
fprintf(f, "%02x", x.data[i]);
|
||||
if (i%32==31) fprintf(f, "\n");
|
||||
}
|
||||
if (x.len%32 != 0) fprintf(f, "\n");
|
||||
fprintf(f, ".\n");
|
||||
}
|
||||
|
||||
// scan data in hex notation.
|
||||
// stop when you reach a non-parsed character.
|
||||
// NOTE: buffer must be big enough.
|
||||
//
|
||||
int scan_hex_data(FILE* f, DATA_BLOCK& x) {
|
||||
int n;
|
||||
x.len = 0;
|
||||
while (1) {
|
||||
n = fscanf(f, "%2x", x.data+x.len);
|
||||
if (n <= 0) break;
|
||||
x.len++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// print a key in ASCII form
|
||||
//
|
||||
int print_key_hex(FILE* f, KEY* key, int size) {
|
||||
int len, i;
|
||||
DATA_BLOCK x;
|
||||
|
||||
fprintf(f, "%d\n", key->bits);
|
||||
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; i<len; i++) {
|
||||
fscanf(f, "%2x", key->data+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;
|
||||
}
|
|
@ -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&);
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
}
|
48
notes
48
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
|
||||
<result>
|
||||
<file_info>
|
||||
<max_size>123123</max_size>
|
||||
</file_info>
|
||||
...
|
||||
</result>
|
||||
|
||||
- RPC reply: result XML info has format
|
||||
<result>
|
||||
<file_info>
|
||||
...
|
||||
<expiration>...</expiration> (added by server)
|
||||
</result>
|
||||
<result_signature>
|
||||
<name>foo</name>
|
||||
... (digital signature of <result> element; added by server)
|
||||
</result_signature>
|
||||
|
||||
- Client stores:
|
||||
for each result (in state file, in memory)
|
||||
exact text of <result> tag
|
||||
signature
|
||||
|
||||
- On file upload, client sends
|
||||
<result> element (exact text)
|
||||
<result_signature>
|
||||
...
|
||||
</result_signature>
|
||||
<filename>blah</filename>
|
||||
<offset>123</offset>
|
||||
<total_size>1234</total_size>
|
||||
<data_start/>
|
||||
... data
|
||||
|
||||
- file upload handler does:
|
||||
parse header (up to <data_start/>)
|
||||
validate signature of <result>
|
||||
verify that filename is in list of file_infos
|
||||
verify that total size is within limit
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// The input to this program looks like this:
|
||||
//
|
||||
// <result>
|
||||
// <file_info>...</file_info>
|
||||
// ...
|
||||
// <signature>
|
||||
// ...
|
||||
// </signature>
|
||||
// </result>
|
||||
// <filename>blah</filename>
|
||||
// ... (data)
|
Loading…
Reference in New Issue