SHAKE-128 Stream Cipher

Introduction

An Extendable-Output Function (XOF) absorbs input of variable length and generates output of variable length. SHAKE128 and SHAKE256 are two such XOFs designed by the Keccak team and included in the SHA-3 standard. They both use a sponge construction and the Keccak(pronounced “ketchak”) permutation function to generate ciphertext streams. The suffixes “128” and “256” indicate the security strength of these functions when the output is of sufficient length. XOFs can be used as a message digest algorithm, a non-reseedable random number generator, for key derivation or as a stream cipher. Here, you’ll see SHAKE128 used as a simple stream cipher. It doesn’t support an Initialization Vector (IV) or nonce, nor does it include authentication. It simply absorbs a 128-bit key and switches to XOF mode before using the output to encrypt data using an exclusive OR operation.

Compact code

This function can be used to initialize a context and encrypt or decrypt a stream of bytes. P is the KECCAK-f[1600] permutation function that is also used by SHA-3. This code is only provided as an example of how one might use SHAKE128 as a stream cipher, and shouldn’t be used for any mission critical application.

#define R(v,n)(((v)>>(n))|((v)<<(64-(n))))
#define F(a,b)for(a=0;a<b;a++)

typedef unsigned long long W;
typedef unsigned char B;

typedef struct _shake_ctx {
    int i;
    union {
      B b[200];
      W q[25];
    } s;
}shake_ctx;

void P(shake_ctx*ctx) {
    W n,i,j,r,x,y,t,Y,b[5],*s=ctx->s.q;
    B c=1;

    F(n,24){
      F(i,5){b[i]=0;F(j,5)b[i]^=s[i+j*5];}
      F(i,5){
        t=b[(i+4)%5]^R(b[(i+1)%5],63);
        F(j,5)s[i+j*5]^=t;}
      t=s[1],y=r=0,x=1;
      F(j,24)
        r+=j+1,Y=(x*2)+(y*3),x=y,y=Y%5,
        Y=s[x+y*5],s[x+y*5]=R(t, -r),t=Y;
      F(j,5){
        F(i,5)b[i]=s[i+j*5];
        F(i,5)
          s[i+j*5]=b[i]^(b[(i+2)%5]&~b[(i+1)%5]);}
      F(j,7)
        if((c=(c<<1)^((c>>7)*113))&2)
          *s^=1ULL<<((1<<j)-1);
    }
}

#define RT (1600 - 256) / 8

void shake128(W len,void*in,shake_ctx*c) {
    W i;

    if(len) {
      F(i,len) {
        if(c->i == RT) {
          P(c); c->i = 0;
        }
        ((B*)in)[i] ^= c->s.b[c->i++];
      }
    } else {
      F(i,25)c->s.q[i]=0; c->i=0;
      F(i,16)c->s.b[i]^=((B*)in)[i];
      c->s.b[16]  ^=0x1F;
      c->s.b[RT-1]^=0x80;
      P(c);
    }
}

sources here.

Advertisements
This entry was posted in cryptography, encryption, programming, security and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s