void seafile_generate_random_key (const char *passwd, char *random_key) { SeafileCrypt *crypt; unsigned char secret_key[32], *rand_key; int outlen; unsigned char key[32], iv[16]; if (RAND_bytes (secret_key, sizeof(secret_key)) != 1) { seaf_warning ("Failed to generate secret key for repo encryption " "with RAND_bytes(), use RAND_pseudo_bytes().\n"); RAND_pseudo_bytes (secret_key, sizeof(secret_key)); } seafile_derive_key (passwd, strlen(passwd), 2, key, iv); crypt = seafile_crypt_new (2, key, iv); seafile_encrypt ((char **)&rand_key, &outlen, (char *)secret_key, sizeof(secret_key), crypt); rawdata_to_hex (rand_key, random_key, 48); g_free (crypt); g_free (rand_key); }
/* token -> AES encrypt with session key -> rawdata_to_hex -> output */ static char * encrypt_token (CcnetProcessor *processor, const char *token) { CcnetPeer *peer = NULL; char *enc_out = NULL; SeafileCrypt *crypt = NULL; unsigned char key[16], iv[16]; int len; char *output = NULL; if (!token) goto out; peer = ccnet_get_peer(seaf->ccnetrpc_client, processor->peer_id); if (!peer || !peer->session_key) { seaf_warning ("[check tx v3] peer or peer session key not exist\n"); goto out; } EVP_BytesToKey (EVP_aes_128_cbc(), /* cipher mode */ EVP_sha1(), /* message digest */ NULL, /* slat */ (unsigned char*)peer->session_key, strlen(peer->session_key), 1, /* iteration times */ key, /* the derived key */ iv); /* IV, initial vector */ crypt = seafile_crypt_new (CURRENT_ENC_VERSION, key, iv); /* encrypt the token with session key, including the trailing null byte */ if (seafile_encrypt (&enc_out, &len, token, strlen(token) + 1, crypt) < 0) { seaf_warning ("[check tx v3] failed to encrypt token\n"); goto out; } output = g_malloc (len * 2 + 1); rawdata_to_hex ((unsigned char *)enc_out, output, len); output[len * 2] = '\0'; out: g_free (crypt); g_free (enc_out); if (peer) g_object_unref(peer); return output; }
/* token -> AES encrypt with session key -> rawdata_to_hex -> output */ static char * encrypt_token (CcnetProcessor *processor, const char *token) { CcnetPeer *peer = NULL; char *enc_out = NULL; SeafileCrypt *crypt = NULL; unsigned char key[16], iv[16]; int len; char *output = NULL; if (!token) goto out; peer = ccnet_get_peer(seaf->ccnetrpc_client, processor->peer_id); if (!peer || !peer->session_key) { seaf_warning ("[check tx v2] peer or peer session key not exist\n"); goto out; } seafile_generate_enc_key (peer->session_key, strlen(peer->session_key), CURRENT_ENC_VERSION, key, iv); crypt = seafile_crypt_new (CURRENT_ENC_VERSION, key, iv); /* encrypt the token with session key, including the trailing null byte */ if (seafile_encrypt (&enc_out, &len, token, strlen(token) + 1, crypt) < 0) { seaf_warning ("[check tx v2] failed to encrypt token\n"); goto out; } output = g_malloc (len * 2 + 1); rawdata_to_hex ((unsigned char *)enc_out, output, len); output[len * 2] = '\0'; out: g_free (crypt); g_free (enc_out); if (peer) g_object_unref(peer); return output; }
int seafile_update_random_key (const char *old_passwd, const char *old_random_key, const char *new_passwd, char *new_random_key) { unsigned char key[32], iv[16]; unsigned char random_key_raw[48], *secret_key, *new_random_key_raw; int secret_key_len, random_key_len; SeafileCrypt *crypt; /* First, use old_passwd to decrypt secret key from old_random_key. */ seafile_derive_key (old_passwd, strlen(old_passwd), 2, key, iv); hex_to_rawdata (old_random_key, random_key_raw, 48); crypt = seafile_crypt_new (2, key, iv); if (seafile_decrypt ((char **)&secret_key, &secret_key_len, (char *)random_key_raw, 48, crypt) < 0) { seaf_warning ("Failed to decrypt random key.\n"); g_free (crypt); return -1; } g_free (crypt); /* Second, use new_passwd to encrypt secret key. */ seafile_derive_key (new_passwd, strlen(new_passwd), 2, key, iv); crypt = seafile_crypt_new (2, key, iv); seafile_encrypt ((char **)&new_random_key_raw, &random_key_len, (char *)secret_key, secret_key_len, crypt); rawdata_to_hex (new_random_key_raw, new_random_key, 48); g_free (secret_key); g_free (new_random_key_raw); g_free (crypt); return 0; }
static int crypt_test (unsigned int len) { if (len <= 0) { g_printf (" [%s] line %d: len must be positive.\n", __func__, __LINE__); return -1; } char *msg = "Hello World!\n"; GString *gstr = g_string_new (NULL); while (gstr->len < len) { g_string_append (gstr, msg); } char *enc_out = NULL; int enc_out_len; g_printf ("[setup] The input is %d bytes\n", len); int res = seafile_encrypt (&enc_out, &enc_out_len, gstr->str, len, CODE, strlen(CODE)); if (res == 0 && enc_out_len != -1) g_printf ("[ENC] [PASS] Encrypted output length is %d bytes\n", enc_out_len); else { g_printf ("[ENC] FAILED.\n"); goto error; } char *dec_out = NULL; int dec_len; res = seafile_decrypt (&dec_out, &dec_len, enc_out, enc_out_len, CODE, strlen(CODE)); if (res != 0 || (unsigned int)dec_len != len || strncmp (dec_out, gstr->str, len) != 0) { g_printf ("[DEC] FAILED.\n"); goto error; } else g_printf ("[DEC] [PASS] Decrypted output is the totally same as input\n"); g_string_free (gstr, TRUE); g_free (enc_out); g_free (dec_out); g_printf ("[TEST] Finished Successfully.\n"); return 0; error: g_string_free (gstr, TRUE); g_free (enc_out); g_free (dec_out); g_printf ("[TEST] FAILED.\n"); return -1; }