1 package org.bouncycastle.crypto.digests; 2 3 import org.bouncycastle.crypto.Xof; 4 5 6 /** 7 * implementation of SHAKE based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ 8 * <p> 9 * Following the naming conventions used in the C source code to enable easy review of the implementation. 10 */ 11 public class SHAKEDigest 12 extends KeccakDigest 13 implements Xof 14 { checkBitLength(int bitLength)15 private static int checkBitLength(int bitLength) 16 { 17 switch (bitLength) 18 { 19 case 128: 20 case 256: 21 return bitLength; 22 default: 23 throw new IllegalArgumentException("'bitLength' " + bitLength + " not supported for SHAKE"); 24 } 25 } 26 SHAKEDigest()27 public SHAKEDigest() 28 { 29 this(128); 30 } 31 SHAKEDigest(int bitLength)32 public SHAKEDigest(int bitLength) 33 { 34 super(checkBitLength(bitLength)); 35 } 36 SHAKEDigest(SHAKEDigest source)37 public SHAKEDigest(SHAKEDigest source) { 38 super(source); 39 } 40 getAlgorithmName()41 public String getAlgorithmName() 42 { 43 return "SHAKE" + fixedOutputLength; 44 } 45 getDigestSize()46 public int getDigestSize() 47 { 48 return fixedOutputLength / 4; 49 } 50 doFinal(byte[] out, int outOff)51 public int doFinal(byte[] out, int outOff) 52 { 53 return doFinal(out, outOff, getDigestSize()); 54 } 55 doFinal(byte[] out, int outOff, int outLen)56 public int doFinal(byte[] out, int outOff, int outLen) 57 { 58 int length = doOutput(out, outOff, outLen); 59 60 reset(); 61 62 return length; 63 } 64 doOutput(byte[] out, int outOff, int outLen)65 public int doOutput(byte[] out, int outOff, int outLen) 66 { 67 if (!squeezing) 68 { 69 absorbBits(0x0F, 4); 70 } 71 72 squeeze(out, outOff, ((long)outLen) * 8); 73 74 return outLen; 75 } 76 77 /* 78 * TODO Possible API change to support partial-byte suffixes. 79 */ doFinal(byte[] out, int outOff, byte partialByte, int partialBits)80 protected int doFinal(byte[] out, int outOff, byte partialByte, int partialBits) 81 { 82 return doFinal(out, outOff, getDigestSize(), partialByte, partialBits); 83 } 84 85 /* 86 * TODO Possible API change to support partial-byte suffixes. 87 */ doFinal(byte[] out, int outOff, int outLen, byte partialByte, int partialBits)88 protected int doFinal(byte[] out, int outOff, int outLen, byte partialByte, int partialBits) 89 { 90 if (partialBits < 0 || partialBits > 7) 91 { 92 throw new IllegalArgumentException("'partialBits' must be in the range [0,7]"); 93 } 94 95 int finalInput = (partialByte & ((1 << partialBits) - 1)) | (0x0F << partialBits); 96 int finalBits = partialBits + 4; 97 98 if (finalBits >= 8) 99 { 100 absorb((byte)finalInput); 101 finalBits -= 8; 102 finalInput >>>= 8; 103 } 104 105 if (finalBits > 0) 106 { 107 absorbBits(finalInput, finalBits); 108 } 109 110 squeeze(out, outOff, ((long)outLen) * 8); 111 112 reset(); 113 114 return outLen; 115 } 116 } 117