int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password ) { struct arc_state *st; unsigned char *key; int key_len, clear_len, i; key_len = strlen( password ) + ARC_IV_LEN; clear_len = crypt_len - ARC_IV_LEN; if( clear_len < 0 ) { *clear = g_strdup( "" ); return 0; } /* Prepare buffers and the key + IV */ *clear = g_malloc( clear_len + 1 ); key = g_malloc( key_len ); strcpy( (char*) key, password ); for( i = 0; i < ARC_IV_LEN; i ++ ) key[key_len-ARC_IV_LEN+i] = crypt[i]; /* Generate the initial S[] from the IVed key. */ st = arc_keymaker( key, key_len, ARC_CYCLES ); g_free( key ); for( i = 0; i < clear_len; i ++ ) clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st ); clear[0][i] = 0; /* Nice to have for plaintexts. */ g_free( st ); return clear_len; }
int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to) { struct arc_state *st; unsigned char *key; char *padded = NULL; int key_len, i, padded_len; key_len = strlen(password) + ARC_IV_LEN; if (clear_len <= 0) { clear_len = strlen(clear); } /* Pad the string to the closest multiple of pad_to. This makes it impossible to see the exact length of the password. */ if (pad_to > 0 && (clear_len % pad_to) > 0) { padded_len = clear_len + pad_to - (clear_len % pad_to); padded = g_malloc(padded_len); memcpy(padded, clear, clear_len); /* First a \0 and then random data, so we don't have to do anything special when decrypting. */ padded[clear_len] = 0; random_bytes((unsigned char *) padded + clear_len + 1, padded_len - clear_len - 1); clear = padded; clear_len = padded_len; } /* Prepare buffers and the key + IV */ *crypt = g_malloc(clear_len + ARC_IV_LEN); key = g_malloc(key_len); strcpy((char *) key, password); /* Add the salt. Save it for later (when decrypting) and, of course, add it to the encryption key. */ random_bytes(crypt[0], ARC_IV_LEN); memcpy(key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN); /* Generate the initial S[] from the IVed key. */ st = arc_keymaker(key, key_len, ARC_CYCLES); g_free(key); for (i = 0; i < clear_len; i++) { crypt[0][i + ARC_IV_LEN] = clear[i] ^ arc_getbyte(st); } g_free(st); g_free(padded); return clear_len + ARC_IV_LEN; }