array and pointers

Matthew Wesley mwesley at acm.org
Thu Jan 25 06:34:06 PST 2007


On Thu, 25 Jan 2007 12:36:53 +0100
Alberto <reda at zioale.it> wrote:

> hi, I have just started to play with D, and I have some little
> problem.
> 
> In C I did something like:
> 
> #define uchar  unsigned char
> 
> void aes_ecb_decrypt(aes_context *ctx, uchar *input, uchar *output,
> uint len ) {
>     int n;
>     uchar *pin, *pout;
> 
>     // test to validate parameters..
> 
>     n = len;
>     pin = input;
>     pout = output;
> 
>     while( n > 0 ) {
>         decrypt_block(ctx, pin, pout );
>         pin  += 16;
>         pout += 16;
>         n -= 16;
>     }
> }
> 
> in D:
> 
> void decrypt_block(ubyte[] input, ubyte[] output) ;
> 
> ubyte[] ecb_decrypt(in ubyte[] input)
> 	in {
> 		assert(input.length > 0);
> 	}
> 	out(output) {
> 		assert(output.length == input.length);
> 	}
> 	body {
> 		int i,n, idx;
> 		ubyte[] pin;
> 		ubyte[] pout;
> 		ubyte[] output;
> 		
> 		n = input.length;
> 		output.length = n;
> 		idx=0;
> 			
> 		while( n > 0 ) {
> 			if (idx+BLOCK_SIZE >= input.length) {
> 				//we must decrypt less then BLOCK_SIZE
> 				decrypt_block(input[idx..$],
> output[idx..$]); } else {
> 				decrypt_block( input[idx..idx+BLOCK_SIZE],
> output[idx..idx+BLOCK_SIZE]); }
> 			idx += BLOCK_SIZE;
> 			n -= BLOCK_SIZE;
> 		}
> 		return output;
> 	}
> 	
> but I don't think that is the right way..
> There is a simpler way using pointers like in C?
> I have tried to use something like:
> 
> 
> 	int n;
> 	ubyte *pin;
> 	ubyte *pout;
> 	ubyte[] output;
> 			
> 	n = input.length;
> 	output.length = n;
> 	pin = input.ptr;
> 	pout = output.ptr;
> 			
> 	while( n > 0 ) {
> 		decrypt_block(cast(ubyte[])pin, cast(ubyte[])pout);
> 		pin  += 16;
> 		pout += 16;
> 		n -= 16;
> 	}
> 
> but I get:
> test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[]
> test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[]
> 
> yes I can modify decrypt_block, but this is not the point, I want just
> understand how can I solve it, in a D way.
> 
> 

The problem you are having is that arrays in D are not like arrays in
C. Think of D arrays as:

struct DArray {
	type *ptr;
	size_t length;
}

This means there is no way to cast from a pointer to a D array, because
D MUST know the length of that array.

Here is my solution to the same ECB problem:

void[] encrypt_ECB(void[] data, void[]to)
in {
    assert(data.length > 0);
    assert(to is null || to.length >= data.length + pad_length(data));
} out(ciphertext) {
    assert(ciphertext.length >= data.length);
    assert(ciphertext.length <= data.length +b_size);
    assert(ciphertext.length % b_size == 0);
 body {
    ubyte pad = pad_length(data);
    size_t total = data.length + pad;
    if(to is null)
          to = new ubyte[total];

     // copy and pad data
     to[0 .. data.length] = data;
     to[data.length .. total] = pad;
     assert(to.length % b_size == 0);

     for(size_t i=0; i < data.length; i += b_size) {
            encipher(output[i .. i+b_size]);
     }

     return to;
}

This is a member function of my BlockCipherAlg abstract class.
Sub-classes of BlockCipherAlg implement encipher(void[]), allowing me
to write one ECB, CBC, PCBC and other chaining method implementations
for all block algorithms. If you're interested, I have a nearly
complete version of my crypto library framework.

-- 
-----------------------------------------------------
PGP public key ID:
pub   2048R/2C19B7E6 2006-02-19 [expires: 2007-02-19]
uid                  Matthew Wesley <mwesley at acm.org>
Find it at http://pgp.mit.edu
-----------------------------------------------------


More information about the Digitalmars-d-learn mailing list