SHACAL-2 Block Cipher

Introduction

SHACAL-1 and SHACAL-2 are block ciphers based on the Secure Hash Standard. They were proposed by Helena Handschuh and David Naccache while both working for the now defunct smartcard company, Gemplus International. SHACAL-1 is an 80 round block cipher built atop of the SHA-1 compression function. It supports a 160-bit block with key sizes of between 128 and 512-bits. SHACAL-2 is a 64 round block cipher built atop of the SHA-256 compression function and supports a larger 256-bit block. Both were submitted to the New European Schemes for Signatures, Integrity and Encryption (NESSIE) project. SHACAL-1 was dropped from the portfolio in 2003 due to concerns about its key schedule, but SHACAL-2 was finally selected. The best known attack against SHACAL-2 is a related-key rectangle attack on round 44 of the 64 rounds in total.

Macros and data types

#define R(v,n)(((v)>>(n))|((v)<<(32-(n))))
#define F(n)for(i=0;i<n;i++)

#define rev32(x) __builtin_bswap32(x)

typedef unsigned long long Q;
typedef unsigned int W;
typedef unsigned char B;

typedef struct _sha256_ctx {
    W s[8];
    union {
      B b[64];
      W w[16];
      Q q[8];
    }x;
    Q len;
}sha256_ctx;

Compact code

The following is not optimized for performance. It’s a simplified version intended to be used as a reference. The mk parameter should point to a key between 128 and 512-bits while data should point to a 256-bit block of plaintext to encrypt.

#define CH(x,y,z)(((x)&(y))^(~(x)&(z)))
#define MAJ(x,y,z)(((x)&(y))^((x)&(z))^((y)&(z)))
#define EP0(x)(R(x,2)^R(x,13)^R(x,22))
#define EP1(x)(R(x,6)^R(x,11)^R(x,25))
#define SIG0(x)(R(x,7)^R(x,18)^((x)>>3))
#define SIG1(x)(R(x,17)^R(x,19)^((x)>>10))

void shacal2(void*mk,void*data) {
    W t1,t2,i,w[64],s[8],*k=mk,*x=data;
    
    W K[64]=
    { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 
      0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
      0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 
      0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
      0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 
      0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
      0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 
      0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
      0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 
      0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
      0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 
      0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
      0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 
      0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
      0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 
      0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; 
    
    // load master key
    F(16)w[i]=rev32(k[i]);
    // expand key
    for(i=16;i<64;i++)
      w[i]=SIG1(w[i-2])+w[i-7]+SIG0(w[i-15])+w[i-16];
    // load 256-bit plaintext
    F(8)s[i]=rev32(x[i]);
    // encrypt
    F(64) {
      t1=s[7]+EP1(s[4])+CH(s[4],s[5],s[6])+w[i]+K[i];
      t2=EP0(s[0])+MAJ(s[0],s[1],s[2]);
      s[7]=s[6],s[6]=s[5],s[5]=s[4],s[4]=s[3]+t1;
      s[3]=s[2],s[2]=s[1],s[1]=s[0],s[0]=t1+t2;
    }
    // store 256-bit ciphertext
    F(8)x[i]=rev32(s[i]);
}

Sources here.

Advertisements
This entry was posted in assembly, cryptography, programming, x86 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