Skip to content

Commit 5595fbb

Browse files
committed
parrallel C implementation of metadata read
1 parent 8709be5 commit 5595fbb

2 files changed

Lines changed: 140 additions & 5 deletions

File tree

git-incrypt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ class CryptRepo:
144144
plugin.globalinit(clearname.encode('utf-8'), url.encode('utf-8'))
145145
if init:
146146
plugin.initbare(clearname.encode('utf-8'))
147+
# plugin.setup_git_directory()
147148
plugin.mktemplate(
148149
init.name.encode('utf-8') if init.name else None,
149150
init.email.encode('utf-8') if init.email else None,
@@ -160,6 +161,7 @@ class CryptRepo:
160161
else:
161162
self.repo = pygit2.Repository('.')
162163
plugin.fetchpattern('_'.encode('utf-8')[0])
164+
plugin.setup_git_directory()
163165
self.meta = MetaData(self.repo)
164166
if forcetrust:
165167
self.trust(force=forcetrust)
@@ -456,6 +458,7 @@ class MetaData:
456458

457459
def read(self):
458460
'read the metadata'
461+
plugin.readmeta()
459462
self.files = {}
460463
tree = self.repo.revparse_single(
461464
plugin.getprefix().decode('utf-8') + '1/_').tree
@@ -473,7 +476,6 @@ class MetaData:
473476
f'Key hash is {newkeyhash}, was {self.keyhash}'
474477
self.keyhash = newkeyhash
475478
keyver, self.key = data.split(b'\x00', 1)
476-
plugin.setcryptkey(self.key)
477479
assert keyver == MetaData.KEYVER, \
478480
f'Key format is {keyver}, expected {MetaData.KEYVER}'
479481
keydata = self._gpg(['-q', '--list-packets'],

incrypt-plugin.c

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "gettext.h"
2323
//#include "config.h"
2424
//#include "environment.h"
25+
#include "object-name.h"
2526

2627
void globalinit(const char* dir, const char* url_arg);
2728
int set_option(const char *name, size_t namelen, const char *value);
@@ -48,11 +49,15 @@ void initbare(const char* dir);
4849
char* mktemplate(const char* name, const char* email, const char* date, const char* msg);
4950
void fetchpattern(const char pattern);
5051
void metainit(void);
52+
void readmeta(void);
5153
char* writemeta(char* output);
5254
int encrypt_buffer_gpg(struct strbuf *buffer, struct strbuf *output,
5355
struct string_list *recipients);
56+
static int decrypt_buffer_gpg(struct strbuf *buffer, struct strbuf *output,
57+
struct strvec *key_ids);
5458
void myupdaterefs(const char* refname, const char* oid);
5559
void encryptstrbuf2obj(struct strbuf* in, struct object_id* obj);
60+
void decryptobj2strbuf(struct object_id* obj, struct strbuf* out);
5661

5762
/*static*/ const char* CRYPTREADME = "# 401 Unauthorized\n\n"
5863
"This is an encrypted git repository. You can clone it, but you will not be\n"
@@ -71,7 +76,10 @@ static struct strbuf url = STRBUF_INIT;
7176
static struct strbuf prefix = STRBUF_INIT;
7277

7378
void globalinit(const char* dir, const char* url_arg) {
74-
chdir(dir);
79+
//int nongit;
80+
if (chdir(dir))
81+
die(_("Could not chdir to '%s'"), dir);
82+
//setup_git_directory_gently(&nongit);
7583
options.verbosity = 1;
7684
options.progress = !!isatty(2);
7785
options.atomic = 0;
@@ -345,6 +353,25 @@ void encryptstrbuf2obj(struct strbuf* in, struct object_id* obj) {
345353
free(encrypted);
346354
}
347355

356+
void decryptobj2strbuf(struct object_id* obj, struct strbuf* out) {
357+
char* data = NULL;
358+
unsigned long datalen;
359+
enum object_type type;
360+
unsigned char* decrypted = NULL;
361+
size_t decryptedlen = 0;
362+
char hash[GIT_SHA1_RAWSZ];
363+
data = odb_read_object(the_repository->objects, obj, &type, &datalen);
364+
decrypted = malloc(datalen+16);
365+
decryptdata((const unsigned char*)data, datalen, decrypted, &decryptedlen);
366+
hashdata((const unsigned char*)decrypted+GIT_SHA1_RAWSZ, decryptedlen-GIT_SHA1_RAWSZ,
367+
(unsigned char*)hash);
368+
if (memcmp(decrypted, hash, GIT_SHA1_RAWSZ))
369+
die("Corrupted encryption data!\n");
370+
strbuf_add(out, decrypted+GIT_SHA1_RAWSZ, decryptedlen-GIT_SHA1_RAWSZ);
371+
free(data);
372+
free(decrypted);
373+
}
374+
348375
unsigned char* hashdata(const unsigned char* input, size_t inputlen,
349376
unsigned char* output) {
350377
struct git_hash_ctx c;
@@ -377,6 +404,7 @@ void initbare(const char* dir) {
377404
}
378405

379406
struct strbuf template = STRBUF_INIT;
407+
struct strbuf defaultbranch = STRBUF_INIT;
380408

381409
char* mktemplate(const char* name, const char* email, const char* date, const char* msg) {
382410
if (!msg)
@@ -427,13 +455,14 @@ void metainit(void) {
427455
struct strbuf keybuf = STRBUF_INIT;
428456
struct strbuf output_buf = STRBUF_INIT;
429457
struct string_list recipients = STRING_LIST_INIT_NODUP;
430-
struct strbuf defaultbranch = STRBUF_INIT;
431458
odb_write_object(the_repository->objects, ver, strlen(ver), OBJ_BLOB, &obj_ver);
432459
strbuf_add(&keybuf, keyver, 15);
433-
getrandom(key, 48, 0);
460+
if (!getrandom(key, 48, 0))
461+
die("getrandom failed");
434462
strbuf_add(&keybuf, key, 48);
435463
/* This hard coded value needs to be replaced later! */
436464
string_list_append(&recipients, "5A8A11E44AD2A1623B84E5AFC5C0C5C7218D18D7");
465+
string_list_append(&recipients, "F2AE0B6CB4089F15A217F12D121F59FB963341A4");
437466
if (encrypt_buffer_gpg(&keybuf, &output_buf, &recipients) < 0)
438467
die("Encryption failed");
439468
strbuf_release(&keybuf);
@@ -453,6 +482,60 @@ static void secretcommit(struct object_id* tid, struct object_id* oid) {
453482
strbuf_release(&commit);
454483
}
455484

485+
void readmeta(void) {
486+
struct strbuf name = STRBUF_INIT;
487+
struct strbuf databuf = STRBUF_INIT;
488+
struct strbuf output_buf = STRBUF_INIT;
489+
struct strvec gpgkeys = STRVEC_INIT;
490+
char* data = NULL;
491+
unsigned long datalen;
492+
enum object_type type;
493+
size_t keyverlen = strlen(keyver);
494+
fprintf(stderr, "===== READ =====\n");
495+
strbuf_addf(&name, "%s1/_:%s", prefix.buf, "ver");
496+
repo_get_oid(the_repository, name.buf, &obj_ver);
497+
fprintf(stderr, "ver: %s\n", oid_to_hex(&obj_ver));
498+
data = odb_read_object(the_repository->objects, &obj_ver, &type, &datalen);
499+
if (strlen(ver) != datalen || memcmp(data, ver, datalen))
500+
die("Version format is %s, expected %s\n", data, ver);
501+
strbuf_release(&name);
502+
free(data);
503+
strbuf_addf(&name, "%s1/_:%s", prefix.buf, "key");
504+
repo_get_oid(the_repository, name.buf, &obj_key);
505+
fprintf(stderr, "key: %s\n", oid_to_hex(&obj_key));
506+
data = odb_read_object(the_repository->objects, &obj_key, &type, &datalen);
507+
strbuf_add(&databuf, data, datalen);
508+
if (decrypt_buffer_gpg(&databuf, &output_buf, &gpgkeys) < 0)
509+
die("Decryption of key failed");
510+
if (strncmp(keyver, output_buf.buf, keyverlen))
511+
die("Key format is %s, expected %s\n", output_buf.buf, keyver);
512+
memcpy(key, output_buf.buf + keyverlen + 1, 48);
513+
for (size_t i = 0; i < gpgkeys.nr; i++) {
514+
fprintf(stderr, "Message was encrypted to key: %s\n", gpgkeys.v[i]);
515+
}
516+
strbuf_release(&name);
517+
free(data);
518+
strbuf_addf(&name, "%s1/_:%s", prefix.buf, "sig");
519+
repo_get_oid(the_repository, name.buf, &obj_sig);
520+
fprintf(stderr, "sig: %s\n", oid_to_hex(&obj_sig));
521+
strbuf_release(&name);
522+
strbuf_addf(&name, "%s1/_:%s", prefix.buf, "msg");
523+
repo_get_oid(the_repository, name.buf, &obj_msg);
524+
fprintf(stderr, "msg: %s\n", oid_to_hex(&obj_msg));
525+
strbuf_release(&template);
526+
decryptobj2strbuf(&obj_msg, &template);
527+
fprintf(stderr, "template: %s\n", template.buf);
528+
strbuf_release(&name);
529+
strbuf_addf(&name, "%s1/_:%s", prefix.buf, "def");
530+
repo_get_oid(the_repository, name.buf, &obj_def);
531+
fprintf(stderr, "def: %s\n", oid_to_hex(&obj_def));
532+
strbuf_release(&defaultbranch);
533+
decryptobj2strbuf(&obj_def, &defaultbranch);
534+
fprintf(stderr, "defaultbranch: %s\n", defaultbranch.buf);
535+
strbuf_release(&name);
536+
fprintf(stderr, "================\n");
537+
}
538+
456539
char* writemeta(char* output) {
457540
struct object_id oid;
458541
struct object_id tid;
@@ -482,7 +565,7 @@ char* writemeta(char* output) {
482565
secretcommit(&tid, &oid);
483566
strbuf_addbuf(&refname, &prefix);
484567
strbuf_addstr(&refname, "1/_");
485-
// refs_update_ref(get_main_ref_store(the_repository), NULL, refname.buf,
568+
//refs_update_ref(get_main_ref_store(the_repository), NULL, refname.buf,
486569
// &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
487570
myupdaterefs(refname.buf, oid_to_hex(&oid));
488571
strbuf_release(&refname);
@@ -529,6 +612,56 @@ int encrypt_buffer_gpg(struct strbuf *buffer, struct strbuf *output,
529612
return 0;
530613
}
531614

615+
static int decrypt_buffer_gpg(struct strbuf *buffer, struct strbuf *output,
616+
struct strvec *key_ids)
617+
{
618+
struct child_process gpg = CHILD_PROCESS_INIT;
619+
int ret;
620+
const char *cp;
621+
struct strbuf gpg_status = STRBUF_INIT;
622+
623+
strvec_pushl(&gpg.args, "gpg", "--decrypt", "--status-fd=2", "--quiet", NULL);
624+
625+
sigchain_push(SIGPIPE, SIG_IGN);
626+
ret = pipe_command(&gpg, buffer->buf, buffer->len,
627+
output, 1024, &gpg_status, 0);
628+
sigchain_pop(SIGPIPE);
629+
630+
for (cp = gpg_status.buf;
631+
cp && (cp = strstr(cp, "[GNUPG:] DECRYPTION_OKAY"));
632+
cp++) {
633+
if (cp == gpg_status.buf || cp[-1] == '\n')
634+
break;
635+
}
636+
637+
ret |= !cp;
638+
if (ret) {
639+
error(_("gpg failed to decrypt the data:\n%s"),
640+
gpg_status.len ? gpg_status.buf : "(no gpg output)");
641+
strbuf_release(&gpg_status);
642+
return -1;
643+
}
644+
645+
for (cp = gpg_status.buf; cp && *cp; ) {
646+
const char *next_line = strchr(cp, '\n');
647+
const char *found;
648+
649+
if (skip_prefix(cp, "[GNUPG:] ENC_TO ", &found)) {
650+
size_t len = strcspn(found, " \n\r");
651+
strvec_pushf(key_ids, "%.*s", (int)len, found);
652+
}
653+
654+
if (next_line)
655+
cp = next_line + 1;
656+
else
657+
break;
658+
}
659+
660+
strbuf_release(&gpg_status);
661+
662+
return 0;
663+
}
664+
532665
int cmd_main(int argc, const char** argv) {
533666
(void)argv;
534667
(void)argc;

0 commit comments

Comments
 (0)