3

I am trying to implement Speck 64bit block / 128bit key cipher in java. I'm stuck at encryption / decryption algorithm. My decryption algorithm can't decrypt cipher text properly.

My implementation:

  • Encryption:

    int m = 4; //key words
    int T = 27; //rounds
    int alpha = 8; //alpha
    int beta = 3; //beta
    int x,y;
    int[] l = new int[2*T], k = new int[T];
    /* *************** KEY EXTENSTION ***************** */
    for(int i = 0; i < T-1; i++) {
        l[i+m-1] = (k[i] + rotateRight(l[i], alpha)) ^ i;
        k[i+1] = rotateLeft(k[i], beta) ^ l[i+m-1]; 
        //System.out.println(k[i]);
    }
    /* *************** ENCRYPTION ********************* */
    for(int i = 0; i < T; i++) {
        x = (rotateLeft(x, alpha) + y) ^ k[i];
        y = rotateRight(y, beta) ^ x;
        //System.out.println(y);
    }
    
  • Decryption:

    /* *************** KEY EXTENSTION ***************** */
    for(int i = 0; i < T-1; i++) {
        l[i+m-1] = (k[i] + rotateRight(l[i], alpha)) ^ i;
        k[i+1] = rotateLeft(k[i], beta) ^ l[i+m-1];
        //System.out.println(k[i]);
    }
    /* *************** DECRYPTION ********************* */         
    for(int i = T-1; i >= 0; i--) {
        y = rotateRight(y, beta) ^ x;
        x = (rotateLeft(x, alpha) - y) ^ k[i];
        //System.out.println(y);
    }
    

x and y are initialized by function boxing(<- little bit weird):

    x = boxing(plainText, 0, 1);
    y = boxing(plainText, 1, 2);

public static int boxing(int[] content, int i, int count) {
    int temp[] = new int[count];
        temp[i] |= content[i*4] & 0xff;
        temp[i] = temp[i] << 8 | content[i*4+1] & 0xff;
        temp[i] = temp[i] << 8 | content[i*4+2] & 0xff;
        temp[i] = temp[i] << 8 | content[i*4+3] & 0xff;
        //System.out.println(temp[from]);

    return temp[i];
}

Note that content is int array of 8 characters.

I put decryption right behind encryption, so I could see if this algorithm is really working, but it isn't and I don't know why. (I reset variables to their proper values, before I used decryption).

References

EDIT:

  • Rotate functions:

    public static int rotateLeft(int number, int amount) {
       return number << amount | number >>> (32-amount);
    }
    public static int rotateRight(int number, int amount) {
       return number >>> amount | number << (32-amount);
    }
    
Amphoru
  • 87
  • 1
  • 11
  • 2
    There are test vectors at the end of the paper in appendix C. How about you first check that encryption works and then check decryption. – Artjom B. Apr 29 '15 at 17:32
  • It seems everything is pretty straightforward, except for the rotate functions, which are missing. – Maarten Bodewes Apr 30 '15 at 13:32
  • Added rotate functions. But mine rotate functions are working at two other ciphers. XTEA and RC5, so I think they're good. – Amphoru Apr 30 '15 at 15:43
  • @Amphoru - Are you able to validate the algorithm using the SPECK test vector? I'm pretty sure the test vectors are wrong (or the authors of the paper omitted necessary information). I modified their reference implementation to operate the cipher in ECB mode and it could not arrive at the test vector result. – jww Nov 20 '17 at 04:55
  • @MaartenBodewes - If you get some time would you take a look at [Noloader | Simon-and-Speck](https://github.com/noloader/Simon-and-Speck). I've spent two days trying to arrive at the published test vector results and I can't seem to do it. The GitHub adds a `main` to the SuperCop reference implementation, and it can't arrive at the test vector results either. – jww Nov 20 '17 at 05:03
  • @jww The test vectors are not wrong but they seem to be given given in big-endian form. The endianness of how input blocks and keys are converted to the two words is not specified in the original document. The authors have commented, that they intended little-endian interpretation: https://en.wikipedia.org/wiki/Speck_(cipher)#Endianness – astraujums Apr 17 '18 at 13:02

1 Answers1

2

Finally figured out. My decryption algorithm should look like this:

    for(int i = T-1; i >= 0; i--) {
        y = rotateRight(x ^ y, beta);
        x = rotateLeft((x ^ k[i]) - y, alpha);
    }

And I accidently swap rotate functions in encryption algorithm. This is correct form:

    for(int i = 0; i < T; i++) {
        x = (rotateRight(x, alpha) + y) ^ k[i];
        y = rotateLeft(y, beta) ^ x;
    }
Amphoru
  • 87
  • 1
  • 11