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; }
struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) { struct arc_state *st; int i, j, tmp; unsigned char S2[256]; st = g_malloc( sizeof( struct arc_state ) ); st->i = st->j = 0; if( kl <= 0 ) kl = strlen( (char*) key ); for( i = 0; i < 256; i ++ ) { st->S[i] = i; S2[i] = key[i%kl]; } for( i = j = 0; i < 256; i ++ ) { j = ( j + st->S[i] + S2[i] ) & 0xff; tmp = st->S[i]; st->S[i] = st->S[j]; st->S[j] = tmp; } memset( S2, 0, 256 ); i = j = 0; for( i = 0; i < cycles; i ++ ) arc_getbyte( st ); return st; }
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; }