summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/crypto/macs
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/macs')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java39
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/GMac.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java77
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/SipHash.java110
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html5
7 files changed, 179 insertions, 89 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
index 1aa8ede4..0492ae69 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMac.java
@@ -58,14 +58,14 @@ public class CMac implements Mac
/**
* create a standard MAC based on a block cipher with the size of the
* MAC been given in bits.
- * <p/>
+ * <p>
* Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
* or 16 bits if being used as a data authenticator (FIPS Publication 113),
* and in general should be less than the size of the block cipher as it reduces
* the chance of an exhaustive attack (see Handbook of Applied Cryptography).
*
* @param cipher the cipher to be used as the basis of the MAC generation.
- * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and <= 128.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and &lt;= 128.
*/
public CMac(BlockCipher cipher, int macSizeInBits)
{
@@ -133,24 +133,31 @@ public class CMac implements Mac
public void init(CipherParameters params)
{
- if (params instanceof KeyParameter)
- {
- cipher.init(true, params);
-
- //initializes the L, Lu, Lu2 numbers
- L = new byte[ZEROES.length];
- cipher.processBlock(ZEROES, 0, L, 0);
- Lu = doubleLu(L);
- Lu2 = doubleLu(Lu);
- } else if (params != null)
- {
- // CMAC mode does not permit IV to underlying CBC mode
- throw new IllegalArgumentException("CMac mode only permits key to be set.");
- }
+ validate(params);
+
+ cipher.init(true, params);
+
+ //initializes the L, Lu, Lu2 numbers
+ L = new byte[ZEROES.length];
+ cipher.processBlock(ZEROES, 0, L, 0);
+ Lu = doubleLu(L);
+ Lu2 = doubleLu(Lu);
reset();
}
+ void validate(CipherParameters params)
+ {
+ if (params != null)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ // CMAC mode does not permit IV to underlying CBC mode
+ throw new IllegalArgumentException("CMac mode only permits key to be set.");
+ }
+ }
+ }
+
public int getMacSize()
{
return macSize;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java
new file mode 100644
index 00000000..a0371d95
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/CMacWithIV.java
@@ -0,0 +1,27 @@
+package org.bouncycastle.crypto.macs;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+
+/**
+ * A non-NIST variant which allows passing of an IV to the underlying CBC cipher.
+ * <p>Note: there isn't really a good reason to use an IV here, use the regular CMac where possible.</p>
+ */
+public class CMacWithIV
+ extends CMac
+{
+ public CMacWithIV(BlockCipher cipher)
+ {
+ super(cipher);
+ }
+
+ public CMacWithIV(BlockCipher cipher, int macSizeInBits)
+ {
+ super(cipher, macSizeInBits);
+ }
+
+ void validate(CipherParameters params)
+ {
+ // accept all
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/GMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/GMac.java
index 8aae1e26..b34f9ea5 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/GMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/GMac.java
@@ -23,7 +23,7 @@ public class GMac implements Mac
/**
* Creates a GMAC based on the operation of a block cipher in GCM mode.
- * <p/>
+ * <p>
* This will produce an authentication code the length of the block size of the cipher.
*
* @param cipher
@@ -40,7 +40,8 @@ public class GMac implements Mac
* Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
*
* @param macSizeBits
- * the mac size to generate, in bits. Must be a multiple of 8 and >= 96 and <= 128.
+ * the mac size to generate, in bits. Must be a multiple of 8 and &gt;= 32 and &lt;= 128.
+ * Sizes less than 96 are not recommended, but are supported for specialized applications.
* @param cipher
* the cipher to be used in GCM mode to generate the MAC.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
index 150eb617..7a346f1e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/Poly1305.java
@@ -7,7 +7,7 @@ import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.util.Pack;
+import org.bouncycastle.util.Pack;
/**
* Poly1305 message authentication code, designed by D. J. Bernstein.
@@ -53,6 +53,14 @@ public class Poly1305
private int h0, h1, h2, h3, h4;
/**
+ * Constructs a Poly1305 MAC, where the key passed to init() will be used directly.
+ */
+ public Poly1305()
+ {
+ this.cipher = null;
+ }
+
+ /**
* Constructs a Poly1305 MAC, using a 128 bit block cipher.
*/
public Poly1305(final BlockCipher cipher)
@@ -66,35 +74,48 @@ public class Poly1305
/**
* Initialises the Poly1305 MAC.
- *
- * @param a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with
- * a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}.
+ *
+ * @param params if used with a block cipher, then a {@link ParametersWithIV} containing a 128 bit
+ * nonce and a {@link KeyParameter} with a 256 bit key complying to the
+ * {@link Poly1305KeyGenerator Poly1305 key format}, otherwise just the
+ * {@link KeyParameter}.
*/
- public void init(final CipherParameters params)
+ public void init(CipherParameters params)
throws IllegalArgumentException
{
- final byte[] nonce;
- final byte[] key;
- if ((params instanceof ParametersWithIV) && ((ParametersWithIV)params).getParameters() instanceof KeyParameter)
+ byte[] nonce = null;
+
+ if (cipher != null)
{
- nonce = ((ParametersWithIV)params).getIV();
- key = ((KeyParameter)((ParametersWithIV)params).getParameters()).getKey();
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException("Poly1305 requires an IV when used with a block cipher.");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+ nonce = ivParams.getIV();
+ params = ivParams.getParameters();
}
- else
+
+ if (!(params instanceof KeyParameter))
{
- throw new IllegalArgumentException("Poly1305 requires a key and and IV.");
+ throw new IllegalArgumentException("Poly1305 requires a key.");
}
- setKey(key, nonce);
+ KeyParameter keyParams = (KeyParameter)params;
+
+ setKey(keyParams.getKey(), nonce);
+
reset();
}
private void setKey(final byte[] key, final byte[] nonce)
{
- if (nonce.length != BLOCK_SIZE)
+ if (cipher != null && (nonce == null || nonce.length != BLOCK_SIZE))
{
throw new IllegalArgumentException("Poly1305 requires a 128 bit IV.");
}
+
Poly1305KeyGenerator.checkKey(key);
// Extract r portion of key
@@ -115,22 +136,28 @@ public class Poly1305
s3 = r3 * 5;
s4 = r4 * 5;
- // Compute encrypted nonce
- final byte[] cipherKey = new byte[BLOCK_SIZE];
- System.arraycopy(key, 0, cipherKey, 0, cipherKey.length);
-
- cipher.init(true, new KeyParameter(cipherKey));
- cipher.processBlock(nonce, 0, cipherKey, 0);
+ final byte[] kBytes;
+ if (cipher == null)
+ {
+ kBytes = key;
+ }
+ else
+ {
+ // Compute encrypted nonce
+ kBytes = new byte[BLOCK_SIZE];
+ cipher.init(true, new KeyParameter(key, 0, BLOCK_SIZE));
+ cipher.processBlock(nonce, 0, kBytes, 0);
+ }
- k0 = Pack.littleEndianToInt(cipherKey, 0);
- k1 = Pack.littleEndianToInt(cipherKey, 4);
- k2 = Pack.littleEndianToInt(cipherKey, 8);
- k3 = Pack.littleEndianToInt(cipherKey, 12);
+ k0 = Pack.littleEndianToInt(kBytes, 0);
+ k1 = Pack.littleEndianToInt(kBytes, 4);
+ k2 = Pack.littleEndianToInt(kBytes, 8);
+ k3 = Pack.littleEndianToInt(kBytes, 12);
}
public String getAlgorithmName()
{
- return "Poly1305-" + cipher.getAlgorithmName();
+ return cipher == null ? "Poly1305" : "Poly1305-" + cipher.getAlgorithmName();
}
public int getMacSize()
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/SipHash.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SipHash.java
index 527c8040..d6b9dbb8 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/SipHash.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SipHash.java
@@ -4,13 +4,12 @@ import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.util.Pack;
-import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Pack;
/**
* Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
* Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
- * <p/>
+ * <p>
* "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
* compression rounds and the number of finalization rounds. A compression round is identical to a
* finalization round and this round function is called SipRound. Given a 128-bit key k and a
@@ -19,14 +18,13 @@ import org.bouncycastle.util.Arrays;
public class SipHash
implements Mac
{
-
protected final int c, d;
protected long k0, k1;
- protected long v0, v1, v2, v3, v4;
+ protected long v0, v1, v2, v3;
- protected byte[] buf = new byte[8];
- protected int bufPos = 0;
+ protected long m = 0;
+ protected int wordPos = 0;
protected int wordCount = 0;
/**
@@ -34,7 +32,7 @@ public class SipHash
*/
public SipHash()
{
- // use of this confuses flow analyser on earlier JDKs.
+ // use of 'this' confuses the flow analyser on earlier JDKs.
this.c = 2;
this.d = 4;
}
@@ -84,12 +82,13 @@ public class SipHash
public void update(byte input)
throws IllegalStateException
{
+ m >>>= 8;
+ m |= (input & 0xffL) << 56;
- buf[bufPos] = input;
- if (++bufPos == buf.length)
+ if (++wordPos == 8)
{
processMessageWord();
- bufPos = 0;
+ wordPos = 0;
}
}
@@ -97,14 +96,41 @@ public class SipHash
throws DataLengthException,
IllegalStateException
{
-
- for (int i = 0; i < length; ++i)
+ int i = 0, fullWords = length & ~7;
+ if (wordPos == 0)
{
- buf[bufPos] = input[offset + i];
- if (++bufPos == buf.length)
+ for (; i < fullWords; i += 8)
{
+ m = Pack.littleEndianToLong(input, offset + i);
processMessageWord();
- bufPos = 0;
+ }
+ for (; i < length; ++i)
+ {
+ m >>>= 8;
+ m |= (input[offset + i] & 0xffL) << 56;
+ }
+ wordPos = length - fullWords;
+ }
+ else
+ {
+ int bits = wordPos << 3;
+ for (; i < fullWords; i += 8)
+ {
+ long n = Pack.littleEndianToLong(input, offset + i);
+ m = (n << bits) | (m >>> -bits);
+ processMessageWord();
+ m = n;
+ }
+ for (; i < length; ++i)
+ {
+ m >>>= 8;
+ m |= (input[offset + i] & 0xffL) << 56;
+
+ if (++wordPos == 8)
+ {
+ processMessageWord();
+ wordPos = 0;
+ }
}
}
}
@@ -112,12 +138,10 @@ public class SipHash
public long doFinal()
throws DataLengthException, IllegalStateException
{
-
- buf[7] = (byte)(((wordCount << 3) + bufPos) & 0xff);
- while (bufPos < 7)
- {
- buf[bufPos++] = 0;
- }
+ // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
+ m >>>= ((7 - wordPos) << 3);
+ m >>>= 8;
+ m |= (((wordCount << 3) + wordPos) & 0xffL) << 56;
processMessageWord();
@@ -135,7 +159,6 @@ public class SipHash
public int doFinal(byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
-
long result = doFinal();
Pack.longToLittleEndian(result, out, outOff);
return 8;
@@ -143,22 +166,19 @@ public class SipHash
public void reset()
{
-
v0 = k0 ^ 0x736f6d6570736575L;
v1 = k1 ^ 0x646f72616e646f6dL;
v2 = k0 ^ 0x6c7967656e657261L;
v3 = k1 ^ 0x7465646279746573L;
- Arrays.fill(buf, (byte)0);
- bufPos = 0;
+ m = 0;
+ wordPos = 0;
wordCount = 0;
}
protected void processMessageWord()
{
-
++wordCount;
- long m = Pack.littleEndianToLong(buf, 0);
v3 ^= m;
applySipRounds(c);
v0 ^= m;
@@ -166,27 +186,31 @@ public class SipHash
protected void applySipRounds(int n)
{
+ long r0 = v0, r1 = v1, r2 = v2, r3 = v3;
+
for (int r = 0; r < n; ++r)
{
- v0 += v1;
- v2 += v3;
- v1 = rotateLeft(v1, 13);
- v3 = rotateLeft(v3, 16);
- v1 ^= v0;
- v3 ^= v2;
- v0 = rotateLeft(v0, 32);
- v2 += v1;
- v0 += v3;
- v1 = rotateLeft(v1, 17);
- v3 = rotateLeft(v3, 21);
- v1 ^= v2;
- v3 ^= v0;
- v2 = rotateLeft(v2, 32);
+ r0 += r1;
+ r2 += r3;
+ r1 = rotateLeft(r1, 13);
+ r3 = rotateLeft(r3, 16);
+ r1 ^= r0;
+ r3 ^= r2;
+ r0 = rotateLeft(r0, 32);
+ r2 += r1;
+ r0 += r3;
+ r1 = rotateLeft(r1, 17);
+ r3 = rotateLeft(r3, 21);
+ r1 ^= r2;
+ r3 ^= r0;
+ r2 = rotateLeft(r2, 32);
}
+
+ v0 = r0; v1 = r1; v2 = r2; v3 = r3;
}
protected static long rotateLeft(long x, int n)
{
- return (x << n) | (x >>> (64 - n));
+ return (x << n) | (x >>> -n);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
index 60972470..7115b510 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/SkeinMac.java
@@ -10,13 +10,12 @@ import org.bouncycastle.crypto.params.SkeinParameters;
/**
* Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
* based on the {@link ThreefishEngine Threefish} tweakable block cipher.
- * <p/>
+ * <p>
* This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
* competition in October 2010.
- * <p/>
+ * <p>
* Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
* Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
- * <p/>
*
* @see SkeinEngine
* @see SkeinParameters
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html
new file mode 100644
index 00000000..0b1f86dd
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/package.html
@@ -0,0 +1,5 @@
+<html>
+<body bgcolor="#ffffff">
+Classes for creating MACs and HMACs.
+</body>
+</html>