summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/crypto
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2013-01-30 18:26:40 -0800
committerBrian Carlstrom <bdc@google.com>2013-02-12 15:18:12 -0800
commit70c8287138e69a98c2f950036f9f703ee37228c8 (patch)
tree4bfe4bc15b03aa8d8500a76bc6829d7511a69653 /bcprov/src/main/java/org/bouncycastle/crypto
parentcb59b9889be18464ca3b9a78ea142c3bafdb289f (diff)
downloadbouncycastle-70c8287138e69a98c2f950036f9f703ee37228c8.tar.gz
bouncycastle 1.48 upgrade
(cherry-picked from e1142c149e244797ce73b0e7fad40816e447a817) Change-Id: Idb04baf42de07b18ddb162e5cd1f98cdadf366f4
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BasicAgreement.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/OutputLengthException.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java19
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java9
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java16
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java17
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java27
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java18
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java125
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java44
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java403
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java50
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java21
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java7
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java117
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java57
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java59
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java5
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java8
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java8
28 files changed, 782 insertions, 336 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java b/bcprov/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
index 85bec735..ddee7019 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
@@ -1,12 +1,14 @@
package org.bouncycastle.crypto;
+import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
/**
* a holding class for public/private parameter pairs.
*/
public class AsymmetricCipherKeyPair
{
- private CipherParameters publicParam;
- private CipherParameters privateParam;
+ private AsymmetricKeyParameter publicParam;
+ private AsymmetricKeyParameter privateParam;
/**
* basic constructor.
@@ -15,19 +17,34 @@ public class AsymmetricCipherKeyPair
* @param privateParam the corresponding private key parameters.
*/
public AsymmetricCipherKeyPair(
- CipherParameters publicParam,
- CipherParameters privateParam)
+ AsymmetricKeyParameter publicParam,
+ AsymmetricKeyParameter privateParam)
{
this.publicParam = publicParam;
this.privateParam = privateParam;
}
/**
+ * basic constructor.
+ *
+ * @param publicParam a public key parameters object.
+ * @param privateParam the corresponding private key parameters.
+ * @deprecated use AsymmetricKeyParameter
+ */
+ public AsymmetricCipherKeyPair(
+ CipherParameters publicParam,
+ CipherParameters privateParam)
+ {
+ this.publicParam = (AsymmetricKeyParameter)publicParam;
+ this.privateParam = (AsymmetricKeyParameter)privateParam;
+ }
+
+ /**
* return the public key parameters.
*
* @return the public key parameters.
*/
- public CipherParameters getPublic()
+ public AsymmetricKeyParameter getPublic()
{
return publicParam;
}
@@ -37,7 +54,7 @@ public class AsymmetricCipherKeyPair
*
* @return the private key parameters.
*/
- public CipherParameters getPrivate()
+ public AsymmetricKeyParameter getPrivate()
{
return privateParam;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/BasicAgreement.java
index 49074272..8e5ff0da 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BasicAgreement.java
@@ -11,11 +11,16 @@ public interface BasicAgreement
/**
* initialise the agreement engine.
*/
- public void init(CipherParameters param);
+ void init(CipherParameters param);
+
+ /**
+ * return the field size for the agreement algorithm in bytes.
+ */
+ int getFieldSize();
/**
* given a public key from a given party calculate the next
* message in the agreement sequence.
*/
- public BigInteger calculateAgreement(CipherParameters pubKey);
+ BigInteger calculateAgreement(CipherParameters pubKey);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index 4878786c..bdb694d4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -201,7 +201,7 @@ public class BufferedBlockCipher
{
if ((outOff + length) > out.length)
{
- throw new DataLengthException("output buffer too short");
+ throw new OutputLengthException("output buffer too short");
}
}
@@ -265,7 +265,7 @@ public class BufferedBlockCipher
if (outOff + bufOff > out.length)
{
- throw new DataLengthException("output buffer too short for doFinal()");
+ throw new OutputLengthException("output buffer too short for doFinal()");
}
if (bufOff != 0)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java b/bcprov/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java
index 59e4b26b..21c150d9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/InvalidCipherTextException.java
@@ -24,4 +24,17 @@ public class InvalidCipherTextException
{
super(message);
}
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ * @param cause the root cause of the exception.
+ */
+ public InvalidCipherTextException(
+ String message,
+ Throwable cause)
+ {
+ super(message, cause);
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/OutputLengthException.java b/bcprov/src/main/java/org/bouncycastle/crypto/OutputLengthException.java
new file mode 100644
index 00000000..62811a2b
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/OutputLengthException.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.crypto;
+
+public class OutputLengthException
+ extends DataLengthException
+{
+ public OutputLengthException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java
index dbf550da..2543b59c 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/PBEParametersGenerator.java
@@ -103,14 +103,21 @@ public abstract class PBEParametersGenerator
public static byte[] PKCS5PasswordToBytes(
char[] password)
{
- byte[] bytes = new byte[password.length];
+ if (password != null)
+ {
+ byte[] bytes = new byte[password.length];
- for (int i = 0; i != bytes.length; i++)
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
{
- bytes[i] = (byte)password[i];
+ return new byte[0];
}
-
- return bytes;
}
/**
@@ -136,7 +143,6 @@ public abstract class PBEParametersGenerator
public static byte[] PKCS12PasswordToBytes(
char[] password)
{
- // BEGIN android-changed
if (password != null && password.length > 0)
{
// +1 for extra 2 pad bytes.
@@ -154,6 +160,5 @@ public abstract class PBEParametersGenerator
{
return new byte[0];
}
- // END android-changed
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
index 40893bf3..d2e2a09f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
@@ -4,10 +4,10 @@ import java.math.BigInteger;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import org.bouncycastle.crypto.params.DHPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
/**
@@ -47,6 +47,11 @@ public class DHBasicAgreement
this.dhParams = key.getParameters();
}
+ public int getFieldSize()
+ {
+ return (key.getParameters().getP().bitLength() + 7) / 8;
+ }
+
/**
* given a short term public key from a given party calculate the next
* message in the agreement sequence.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
index 3ad3e1ca..59944e07 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -2,12 +2,11 @@ package org.bouncycastle.crypto.agreement;
import java.math.BigInteger;
-import org.bouncycastle.math.ec.ECPoint;
-
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.math.ec.ECPoint;
/**
* P1363 7.2.1 ECSVDP-DH
@@ -34,6 +33,11 @@ public class ECDHBasicAgreement
this.key = (ECPrivateKeyParameters)key;
}
+ public int getFieldSize()
+ {
+ return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
public BigInteger calculateAgreement(
CipherParameters pubKey)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
index 8bcfe260..d8ec62b1 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -201,10 +201,20 @@ public class PKCS1Encoding
}
byte type = block[0];
-
- if (type != 1 && type != 2)
+
+ if (forPrivateKey)
+ {
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
{
- throw new InvalidCipherTextException("unknown block type");
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
}
// BEGIN android-added
if ((type == 1 && forPrivateKey) || (type == 2 && !forPrivateKey))
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
index d9bb482e..1bc9aaea 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
@@ -219,9 +219,7 @@ private static final int[] Tinv0 =
0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
0x4257b8d0};
- private int shift(
- int r,
- int shift)
+ private static int shift(int r, int shift)
{
return (r >>> shift) | (r << -shift);
}
@@ -232,7 +230,7 @@ private static final int[] Tinv0 =
private static final int m2 = 0x7f7f7f7f;
private static final int m3 = 0x0000001b;
- private int FFmulX(int x)
+ private static int FFmulX(int x)
{
return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
}
@@ -247,7 +245,7 @@ private static final int[] Tinv0 =
*/
- private int inv_mcol(int x)
+ private static int inv_mcol(int x)
{
int f2 = FFmulX(x);
int f4 = FFmulX(f2);
@@ -257,7 +255,7 @@ private static final int[] Tinv0 =
return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
}
- private int subWord(int x)
+ private static int subWord(int x)
{
return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
index 2374be1f..7e91973d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java
@@ -3,6 +3,9 @@ package org.bouncycastle.crypto.engines;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+// BEGIN android-added
+import org.bouncycastle.crypto.OutputLengthException;
+// END android-added
import org.bouncycastle.crypto.params.KeyParameter;
/**
@@ -549,9 +552,7 @@ public class AESFastEngine
0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
0xd04257b8};
- private int shift(
- int r,
- int shift)
+ private static int shift(int r, int shift)
{
return (r >>> shift) | (r << -shift);
}
@@ -562,7 +563,7 @@ public class AESFastEngine
private static final int m2 = 0x7f7f7f7f;
private static final int m3 = 0x0000001b;
- private int FFmulX(int x)
+ private static int FFmulX(int x)
{
return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
}
@@ -577,7 +578,7 @@ public class AESFastEngine
*/
- private int inv_mcol(int x)
+ private static int inv_mcol(int x)
{
int f2 = FFmulX(x);
int f4 = FFmulX(f2);
@@ -588,7 +589,7 @@ public class AESFastEngine
}
- private int subWord(int x)
+ private static int subWord(int x)
{
return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
}
@@ -725,7 +726,9 @@ public class AESFastEngine
if ((outOff + (32 / 2)) > out.length)
{
- throw new DataLengthException("output buffer too short");
+ // BEGIN android-changed
+ throw new OutputLengthException("output buffer too short");
+ // END android-changed
}
if (forEncryption)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java
index d1935eca..c9082183 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeEngine.java
@@ -2,6 +2,9 @@ package org.bouncycastle.crypto.engines;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
+// BEGIN android-added
+import org.bouncycastle.crypto.OutputLengthException;
+// END android-added
import org.bouncycastle.crypto.params.KeyParameter;
/**
@@ -99,7 +102,9 @@ public class DESedeEngine
if ((outOff + BLOCK_SIZE) > out.length)
{
- throw new DataLengthException("output buffer too short");
+ // BEGIN android-changed
+ throw new OutputLengthException("output buffer too short");
+ // END android-changed
}
byte[] temp = new byte[BLOCK_SIZE];
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java b/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java
index c0c83335..f5b931de 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/macs/HMac.java
@@ -7,6 +7,7 @@ import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.util.Integers;
/**
* HMAC implementation based on RFC2104
@@ -33,29 +34,29 @@ public class HMac
blockLengths = new Hashtable();
// BEGIN android-removed
- // blockLengths.put("GOST3411", Integer.valueOf(32));
+ // blockLengths.put("GOST3411", Integers.valueOf(32));
//
- // blockLengths.put("MD2", Integer.valueOf(16));
- // blockLengths.put("MD4", Integer.valueOf(64));
+ // blockLengths.put("MD2", Integers.valueOf(16));
+ // blockLengths.put("MD4", Integers.valueOf(64));
// END android-removed
- blockLengths.put("MD5", Integer.valueOf(64));
+ blockLengths.put("MD5", Integers.valueOf(64));
// BEGIN android-removed
- // blockLengths.put("RIPEMD128", Integer.valueOf(64));
- // blockLengths.put("RIPEMD160", Integer.valueOf(64));
+ // blockLengths.put("RIPEMD128", Integers.valueOf(64));
+ // blockLengths.put("RIPEMD160", Integers.valueOf(64));
// END android-removed
- blockLengths.put("SHA-1", Integer.valueOf(64));
+ blockLengths.put("SHA-1", Integers.valueOf(64));
// BEGIN android-removed
- // blockLengths.put("SHA-224", Integer.valueOf(64));
+ // blockLengths.put("SHA-224", Integers.valueOf(64));
// END android-removed
- blockLengths.put("SHA-256", Integer.valueOf(64));
- blockLengths.put("SHA-384", Integer.valueOf(128));
- blockLengths.put("SHA-512", Integer.valueOf(128));
+ blockLengths.put("SHA-256", Integers.valueOf(64));
+ blockLengths.put("SHA-384", Integers.valueOf(128));
+ blockLengths.put("SHA-512", Integers.valueOf(128));
// BEGIN android-removed
- // blockLengths.put("Tiger", Integer.valueOf(64));
- // blockLengths.put("Whirlpool", Integer.valueOf(64));
+ // blockLengths.put("Tiger", Integers.valueOf(64));
+ // blockLengths.put("Whirlpool", Integers.valueOf(64));
// END android-removed
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
index 3c3bf341..71b75954 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/AEADBlockCipher.java
@@ -36,6 +36,24 @@ public interface AEADBlockCipher
public BlockCipher getUnderlyingCipher();
/**
+ * Add a single byte to the associated data check.
+ * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the byte to be processed.
+ */
+ public void processAADByte(byte in);
+
+ /**
+ * Add a sequence of bytes to the associated data check.
+ * <br>If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ */
+ public void processAADBytes(byte[] in, int inOff, int len);
+
+ /**
* encrypt/decrypt a single byte.
*
* @param in the byte to be processed.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java
index 1219f6db..d4800e62 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CBCBlockCipher.java
@@ -93,7 +93,7 @@ public class CBCBlockCipher
{
reset();
- // if it;s null key is to be reused.
+ // if it's null, key is to be reused.
if (params != null)
{
cipher.init(encrypting, params);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index bedc3d13..18a34253 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -25,10 +25,11 @@ public class CCMBlockCipher
private int blockSize;
private boolean forEncryption;
private byte[] nonce;
- private byte[] associatedText;
+ private byte[] initialAssociatedText;
private int macSize;
private CipherParameters keyParam;
private byte[] macBlock;
+ private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
private ByteArrayOutputStream data = new ByteArrayOutputStream();
/**
@@ -69,7 +70,7 @@ public class CCMBlockCipher
AEADParameters param = (AEADParameters)params;
nonce = param.getNonce();
- associatedText = param.getAssociatedText();
+ initialAssociatedText = param.getAssociatedText();
macSize = param.getMacSize() / 8;
keyParam = param.getKey();
}
@@ -78,7 +79,7 @@ public class CCMBlockCipher
ParametersWithIV param = (ParametersWithIV)params;
nonce = param.getIV();
- associatedText = null;
+ initialAssociatedText = null;
macSize = macBlock.length / 2;
keyParam = param.getParameters();
}
@@ -93,6 +94,17 @@ public class CCMBlockCipher
return cipher.getAlgorithmName() + "/CCM";
}
+ public void processAADByte(byte in)
+ {
+ associatedText.write(in);
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ // TODO: Process AAD online
+ associatedText.write(in, inOff, len);
+ }
+
public int processByte(byte in, byte[] out, int outOff)
throws DataLengthException, IllegalStateException
{
@@ -125,6 +137,7 @@ public class CCMBlockCipher
public void reset()
{
cipher.reset();
+ associatedText.reset();
data.reset();
}
@@ -150,60 +163,62 @@ public class CCMBlockCipher
public int getOutputSize(int len)
{
+ int totalData = len + data.size();
+
if (forEncryption)
{
- return data.size() + len + macSize;
- }
- else
- {
- return data.size() + len - macSize;
+ return totalData + macSize;
}
+
+ return totalData < macSize ? 0 : totalData - macSize;
}
public byte[] processPacket(byte[] in, int inOff, int inLen)
throws IllegalStateException, InvalidCipherTextException
{
+ // TODO: handle null keyParam (e.g. via RepeatedKeySpec)
+ // Need to keep the CTR and CBC Mac parts around and reset
if (keyParam == null)
{
throw new IllegalStateException("CCM cipher unitialized.");
}
-
+
BlockCipher ctrCipher = new SICBlockCipher(cipher);
byte[] iv = new byte[blockSize];
byte[] out;
iv[0] = (byte)(((15 - nonce.length) - 1) & 0x7);
-
+
System.arraycopy(nonce, 0, iv, 1, nonce.length);
-
+
ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
-
+
if (forEncryption)
{
int index = inOff;
int outOff = 0;
-
+
out = new byte[inLen + macSize];
-
+
calculateMac(in, inOff, inLen, macBlock);
-
+
ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
-
+
while (index < inLen - blockSize) // S1...
{
ctrCipher.processBlock(in, index, out, outOff);
outOff += blockSize;
index += blockSize;
}
-
+
byte[] block = new byte[blockSize];
-
+
System.arraycopy(in, index, block, 0, inLen - index);
-
+
ctrCipher.processBlock(block, 0, block, 0);
-
+
System.arraycopy(block, 0, out, outOff, inLen - index);
-
+
outOff += inLen - index;
System.arraycopy(macBlock, 0, out, outOff, out.length - outOff);
@@ -212,49 +227,49 @@ public class CCMBlockCipher
{
int index = inOff;
int outOff = 0;
-
+
out = new byte[inLen - macSize];
-
+
System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize);
-
+
ctrCipher.processBlock(macBlock, 0, macBlock, 0);
-
+
for (int i = macSize; i != macBlock.length; i++)
{
macBlock[i] = 0;
}
-
+
while (outOff < out.length - blockSize)
{
ctrCipher.processBlock(in, index, out, outOff);
outOff += blockSize;
index += blockSize;
}
-
+
byte[] block = new byte[blockSize];
-
+
System.arraycopy(in, index, block, 0, out.length - outOff);
-
+
ctrCipher.processBlock(block, 0, block, 0);
-
+
System.arraycopy(block, 0, out, outOff, out.length - outOff);
-
+
byte[] calculatedMacBlock = new byte[blockSize];
-
+
calculateMac(out, 0, out.length, calculatedMacBlock);
-
+
if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
{
throw new InvalidCipherTextException("mac check in CCM failed");
}
}
-
+
return out;
}
-
+
private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
{
- Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
+ Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
cMac.init(keyParam);
@@ -292,10 +307,11 @@ public class CCMBlockCipher
{
int extra;
- if (associatedText.length < ((1 << 16) - (1 << 8)))
+ int textLength = getAssociatedTextLength();
+ if (textLength < ((1 << 16) - (1 << 8)))
{
- cMac.update((byte)(associatedText.length >> 8));
- cMac.update((byte)associatedText.length);
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
extra = 2;
}
@@ -303,17 +319,25 @@ public class CCMBlockCipher
{
cMac.update((byte)0xff);
cMac.update((byte)0xfe);
- cMac.update((byte)(associatedText.length >> 24));
- cMac.update((byte)(associatedText.length >> 16));
- cMac.update((byte)(associatedText.length >> 8));
- cMac.update((byte)associatedText.length);
+ cMac.update((byte)(textLength >> 24));
+ cMac.update((byte)(textLength >> 16));
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
extra = 6;
}
-
- cMac.update(associatedText, 0, associatedText.length);
-
- extra = (extra + associatedText.length) % 16;
+
+ if (initialAssociatedText != null)
+ {
+ cMac.update(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ if (associatedText.size() > 0)
+ {
+ byte[] tmp = associatedText.toByteArray();
+ cMac.update(tmp, 0, tmp.length);
+ }
+
+ extra = (extra + textLength) % 16;
if (extra != 0)
{
for (int i = 0; i != 16 - extra; i++)
@@ -331,8 +355,13 @@ public class CCMBlockCipher
return cMac.doFinal(macBlock, 0);
}
+ private int getAssociatedTextLength()
+ {
+ return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
+ }
+
private boolean hasAssociatedText()
{
- return associatedText != null && associatedText.length != 0;
+ return getAssociatedTextLength() > 0;
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index 0af49f4d..d0fb9bb6 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -68,36 +68,40 @@ public class CFBBlockCipher
if (params instanceof ParametersWithIV)
{
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
- if (iv.length < IV.length)
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
{
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
+ IV[i] = 0;
}
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
- reset();
+ reset();
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
- {
- cipher.init(true, ivParam.getParameters());
- }
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
}
else
{
- reset();
+ reset();
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
cipher.init(true, params);
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index 7c98efae..9e617ec9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -4,7 +4,9 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
+import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;
@@ -20,28 +22,31 @@ public class GCMBlockCipher
implements AEADBlockCipher
{
private static final int BLOCK_SIZE = 16;
- private static final byte[] ZEROES = new byte[BLOCK_SIZE];
// not final due to a compiler bug
private BlockCipher cipher;
private GCMMultiplier multiplier;
+ private GCMExponentiator exp;
// These fields are set by init and not modified by processing
private boolean forEncryption;
private int macSize;
private byte[] nonce;
- private byte[] A;
+ private byte[] initialAssociatedText;
private byte[] H;
- private byte[] initS;
private byte[] J0;
// These fields are modified during processing
private byte[] bufBlock;
private byte[] macBlock;
- private byte[] S;
+ private byte[] S, S_at, S_atPre;
private byte[] counter;
private int bufOff;
private long totalLength;
+ private byte[] atBlock;
+ private int atBlockPos;
+ private long atLength;
+ private long atLengthPre;
public GCMBlockCipher(BlockCipher c)
{
@@ -82,14 +87,14 @@ public class GCMBlockCipher
this.forEncryption = forEncryption;
this.macBlock = null;
- KeyParameter keyParam;
+ KeyParameter keyParam;
if (params instanceof AEADParameters)
{
AEADParameters param = (AEADParameters)params;
nonce = param.getNonce();
- A = param.getAssociatedText();
+ initialAssociatedText = param.getAssociatedText();
int macSizeBits = param.getMacSize();
if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0)
@@ -105,7 +110,7 @@ public class GCMBlockCipher
ParametersWithIV param = (ParametersWithIV)params;
nonce = param.getIV();
- A = null;
+ initialAssociatedText = null;
macSize = 16;
keyParam = (KeyParameter)param.getParameters();
}
@@ -122,48 +127,54 @@ public class GCMBlockCipher
throw new IllegalArgumentException("IV must be at least 1 byte");
}
- if (A == null)
- {
- // Avoid lots of null checks
- A = new byte[0];
- }
+ // TODO This should be configurable by init parameters
+ // (but must be 16 if nonce length not 12) (BLOCK_SIZE?)
+// this.tagLength = 16;
// Cipher always used in forward mode
// if keyParam is null we're reusing the last key.
if (keyParam != null)
{
cipher.init(true, keyParam);
- }
- // TODO This should be configurable by init parameters
- // (but must be 16 if nonce length not 12) (BLOCK_SIZE?)
-// this.tagLength = 16;
+ this.H = new byte[BLOCK_SIZE];
+ cipher.processBlock(H, 0, H, 0);
- this.H = new byte[BLOCK_SIZE];
- cipher.processBlock(ZEROES, 0, H, 0);
- multiplier.init(H);
+ // GCMMultiplier tables don't change unless the key changes (and are expensive to init)
+ multiplier.init(H);
+ exp = null;
+ }
- this.initS = gHASH(A);
+ this.J0 = new byte[BLOCK_SIZE];
if (nonce.length == 12)
{
- this.J0 = new byte[16];
System.arraycopy(nonce, 0, J0, 0, nonce.length);
- this.J0[15] = 0x01;
+ this.J0[BLOCK_SIZE - 1] = 0x01;
}
else
{
- this.J0 = gHASH(nonce);
- byte[] X = new byte[16];
- packLength((long)nonce.length * 8, X, 8);
- xor(this.J0, X);
- multiplier.multiplyH(this.J0);
+ gHASH(J0, nonce, nonce.length);
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian((long)nonce.length * 8, X, 8);
+ gHASHBlock(J0, X);
}
- this.S = Arrays.clone(initS);
+ this.S = new byte[BLOCK_SIZE];
+ this.S_at = new byte[BLOCK_SIZE];
+ this.S_atPre = new byte[BLOCK_SIZE];
+ this.atBlock = new byte[BLOCK_SIZE];
+ this.atBlockPos = 0;
+ this.atLength = 0;
+ this.atLengthPre = 0;
this.counter = Arrays.clone(J0);
this.bufOff = 0;
this.totalLength = 0;
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
}
public byte[] getMac()
@@ -173,23 +184,88 @@ public class GCMBlockCipher
public int getOutputSize(int len)
{
+ int totalData = len + bufOff;
+
if (forEncryption)
{
- return len + bufOff + macSize;
+ return totalData + macSize;
}
- return len + bufOff - macSize;
+ return totalData < macSize ? 0 : totalData - macSize;
}
public int getUpdateOutputSize(int len)
{
- return ((len + bufOff) / BLOCK_SIZE) * BLOCK_SIZE;
+ int totalData = len + bufOff;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % BLOCK_SIZE;
+ }
+
+ public void processAADByte(byte in)
+ {
+ atBlock[atBlockPos] = in;
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ atBlock[atBlockPos] = in[inOff + i];
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+ }
+
+ private void initCipher()
+ {
+ if (atLength > 0)
+ {
+ System.arraycopy(S_at, 0, S_atPre, 0, BLOCK_SIZE);
+ atLengthPre = atLength;
+ }
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_atPre, atBlock, 0, atBlockPos);
+ atLengthPre += atBlockPos;
+ }
+
+ if (atLengthPre > 0)
+ {
+ System.arraycopy(S_atPre, 0, S, 0, BLOCK_SIZE);
+ }
}
public int processByte(byte in, byte[] out, int outOff)
throws DataLengthException
{
- return process(in, out, outOff);
+ bufBlock[bufOff] = in;
+ if (++bufOff == bufBlock.length)
+ {
+ outputBlock(out, outOff);
+ return BLOCK_SIZE;
+ }
+ return 0;
}
public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
@@ -197,21 +273,12 @@ public class GCMBlockCipher
{
int resultLen = 0;
- for (int i = 0; i != len; i++)
+ for (int i = 0; i < len; ++i)
{
-// resultLen += process(in[inOff + i], out, outOff + resultLen);
- bufBlock[bufOff++] = in[inOff + i];
-
- if (bufOff == bufBlock.length)
+ bufBlock[bufOff] = in[inOff + i];
+ if (++bufOff == bufBlock.length)
{
- gCTRBlock(bufBlock, BLOCK_SIZE, out, outOff + resultLen);
- if (!forEncryption)
- {
- System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
- }
-// bufOff = 0;
- bufOff = bufBlock.length - BLOCK_SIZE;
-// return bufBlock.Length;
+ outputBlock(out, outOff + resultLen);
resultLen += BLOCK_SIZE;
}
}
@@ -219,30 +286,32 @@ public class GCMBlockCipher
return resultLen;
}
- private int process(byte in, byte[] out, int outOff)
- throws DataLengthException
+ private void outputBlock(byte[] output, int offset)
{
- bufBlock[bufOff++] = in;
-
- if (bufOff == bufBlock.length)
+ if (totalLength == 0)
{
- gCTRBlock(bufBlock, BLOCK_SIZE, out, outOff);
- if (!forEncryption)
- {
- System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
- }
-// bufOff = 0;
- bufOff = bufBlock.length - BLOCK_SIZE;
-// return bufBlock.length;
- return BLOCK_SIZE;
+ initCipher();
+ }
+ gCTRBlock(bufBlock, output, offset);
+ if (forEncryption)
+ {
+ bufOff = 0;
+ }
+ else
+ {
+ System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
+ bufOff = macSize;
}
-
- return 0;
}
public int doFinal(byte[] out, int outOff)
throws IllegalStateException, InvalidCipherTextException
{
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
+
int extra = bufOff;
if (!forEncryption)
{
@@ -255,18 +324,57 @@ public class GCMBlockCipher
if (extra > 0)
{
- byte[] tmp = new byte[BLOCK_SIZE];
- System.arraycopy(bufBlock, 0, tmp, 0, extra);
- gCTRBlock(tmp, extra, out, outOff);
+ gCTRPartial(bufBlock, 0, extra, out, outOff);
+ }
+
+ atLength += atBlockPos;
+
+ if (atLength > atLengthPre)
+ {
+ /*
+ * Some AAD was sent after the cipher started. We determine the difference b/w the hash value
+ * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
+ * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
+ * partial) cipher-text blocks produced, and adjust the current hash.
+ */
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_at, atBlock, 0, atBlockPos);
+ }
+
+ // Find the difference between the AAD hashes
+ if (atLengthPre > 0)
+ {
+ xor(S_at, S_atPre);
+ }
+
+ // Number of cipher-text blocks produced
+ long c = ((totalLength * 8) + 127) >>> 7;
+
+ // Calculate the adjustment factor
+ byte[] H_c = new byte[16];
+ if (exp == null)
+ {
+ exp = new Tables1kGCMExponentiator();
+ exp.init(H);
+ }
+ exp.exponentiateX(c, H_c);
+
+ // Carry the difference forward
+ multiply(S_at, H_c);
+
+ // Adjust the current hash
+ xor(S, S_at);
}
// Final gHASH
- byte[] X = new byte[16];
- packLength((long)A.length * 8, X, 0);
- packLength(totalLength * 8, X, 8);
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian(atLength * 8, X, 0);
+ Pack.longToBigEndian(totalLength * 8, X, 8);
- xor(S, X);
- multiplier.multiplyH(S);
+ gHASHBlock(S, X);
// TODO Fix this if tagLength becomes configurable
// T = MSBt(GCTRk(J0,S))
@@ -310,7 +418,15 @@ public class GCMBlockCipher
private void reset(
boolean clearMac)
{
- S = Arrays.clone(initS);
+ cipher.reset();
+
+ S = new byte[BLOCK_SIZE];
+ S_at = new byte[BLOCK_SIZE];
+ S_atPre = new byte[BLOCK_SIZE];
+ atBlock = new byte[BLOCK_SIZE];
+ atBlockPos = 0;
+ atLength = 0;
+ atLengthPre = 0;
counter = Arrays.clone(J0);
bufOff = 0;
totalLength = 0;
@@ -325,12 +441,59 @@ public class GCMBlockCipher
macBlock = null;
}
- cipher.reset();
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ private void gCTRBlock(byte[] block, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, block);
+ System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
+
+ gHASHBlock(S, forEncryption ? tmp : block);
+
+ totalLength += BLOCK_SIZE;
+ }
+
+ private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, buf, off, len);
+ System.arraycopy(tmp, 0, out, outOff, len);
+
+ gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
+
+ totalLength += len;
+ }
+
+ private void gHASH(byte[] Y, byte[] b, int len)
+ {
+ for (int pos = 0; pos < len; pos += BLOCK_SIZE)
+ {
+ int num = Math.min(len - pos, BLOCK_SIZE);
+ gHASHPartial(Y, b, pos, num);
+ }
+ }
+
+ private void gHASHBlock(byte[] Y, byte[] b)
+ {
+ xor(Y, b);
+ multiplier.multiplyH(Y);
+ }
+
+ private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
+ {
+ xor(Y, b, off, len);
+ multiplier.multiplyH(Y);
}
- private void gCTRBlock(byte[] buf, int bufCount, byte[] out, int outOff)
+ private byte[] getNextCounterBlock()
{
-// inc(counter);
for (int i = 15; i >= 12; --i)
{
byte b = (byte)((counter[i] + 1) & 0xff);
@@ -343,68 +506,56 @@ public class GCMBlockCipher
}
byte[] tmp = new byte[BLOCK_SIZE];
+ // TODO Sure would be nice if ciphers could operate on int[]
cipher.processBlock(counter, 0, tmp, 0);
+ return tmp;
+ }
- byte[] hashBytes;
- if (forEncryption)
- {
- System.arraycopy(ZEROES, bufCount, tmp, bufCount, BLOCK_SIZE - bufCount);
- hashBytes = tmp;
- }
- else
- {
- hashBytes = buf;
- }
+ private static void multiply(byte[] block, byte[] val)
+ {
+ byte[] tmp = Arrays.clone(block);
+ byte[] c = new byte[16];
- for (int i = bufCount - 1; i >= 0; --i)
+ for (int i = 0; i < 16; ++i)
{
- tmp[i] ^= buf[i];
- out[outOff + i] = tmp[i];
- }
+ byte bits = val[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(c, tmp);
+ }
-// gHASHBlock(hashBytes);
- xor(S, hashBytes);
- multiplier.multiplyH(S);
+ boolean lsb = (tmp[15] & 1) != 0;
+ shiftRight(tmp);
+ if (lsb)
+ {
+ // R = new byte[]{ 0xe1, ... };
+// xor(v, R);
+ tmp[0] ^= (byte)0xe1;
+ }
+ }
+ }
- totalLength += bufCount;
+ System.arraycopy(c, 0, block, 0, 16);
}
- private byte[] gHASH(byte[] b)
+ private static void shiftRight(byte[] block)
{
- byte[] Y = new byte[16];
-
- for (int pos = 0; pos < b.length; pos += 16)
+ int i = 0;
+ int bit = 0;
+ for (;;)
{
- byte[] X = new byte[16];
- int num = Math.min(b.length - pos, 16);
- System.arraycopy(b, pos, X, 0, num);
- xor(Y, X);
- multiplier.multiplyH(Y);
+ int b = block[i] & 0xff;
+ block[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
}
-
- return Y;
}
-// private void gHASHBlock(byte[] block)
-// {
-// xor(S, block);
-// multiplier.multiplyH(S);
-// }
-
-// private static void inc(byte[] block)
-// {
-// for (int i = 15; i >= 12; --i)
-// {
-// byte b = (byte)((block[i] + 1) & 0xff);
-// block[i] = b;
-//
-// if (b != 0)
-// {
-// break;
-// }
-// }
-// }
-
private static void xor(byte[] block, byte[] val)
{
for (int i = 15; i >= 0; --i)
@@ -413,9 +564,11 @@ public class GCMBlockCipher
}
}
- private static void packLength(long count, byte[] bs, int off)
+ private static void xor(byte[] block, byte[] val, int off, int len)
{
- Pack.intToBigEndian((int)(count >>> 32), bs, off);
- Pack.intToBigEndian((int)count, bs, off + 4);
+ while (len-- > 0)
+ {
+ block[len] ^= val[off + len];
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
index 728a2e7a..5297698f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OFBBlockCipher.java
@@ -65,36 +65,40 @@ public class OFBBlockCipher
{
if (params instanceof ParametersWithIV)
{
- ParametersWithIV ivParam = (ParametersWithIV)params;
- byte[] iv = ivParam.getIV();
-
- if (iv.length < IV.length)
- {
- // prepend the supplied IV with zeros (per FIPS PUB 81)
- System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
- for (int i = 0; i < IV.length - iv.length; i++)
- {
- IV[i] = 0;
- }
- }
- else
- {
- System.arraycopy(iv, 0, IV, 0, IV.length);
- }
-
- reset();
-
- // if null it's an IV changed only.
- if (ivParam.getParameters() != null)
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
{
- cipher.init(true, ivParam.getParameters());
+ IV[i] = 0;
}
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
}
else
{
- reset();
+ reset();
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
cipher.init(true, params);
+ }
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
index af9f18db..da8c4ae1 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
@@ -9,7 +9,8 @@ import org.bouncycastle.crypto.params.ParametersWithIV;
* Implements the Segmented Integer Counter (SIC) mode on top of a simple
* block cipher. This mode is also known as CTR mode.
*/
-public class SICBlockCipher implements BlockCipher
+public class SICBlockCipher
+ implements BlockCipher
{
private final BlockCipher cipher;
private final int blockSize;
@@ -94,22 +95,10 @@ public class SICBlockCipher implements BlockCipher
out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]);
}
- int carry = 1;
-
- for (int i = counter.length - 1; i >= 0; i--)
+ // increment counter by 1.
+ for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
{
- int x = (counter[i] & 0xff) + carry;
-
- if (x > 0xff)
- {
- carry = 1;
- }
- else
- {
- carry = 0;
- }
-
- counter[i] = (byte)x;
+ ; // do nothing - pre-increment and test for 0 in counter does the job.
}
return counter.length;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java
new file mode 100644
index 00000000..e1cc5c76
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java
@@ -0,0 +1,7 @@
+package org.bouncycastle.crypto.modes.gcm;
+
+public interface GCMExponentiator
+{
+ void init(byte[] x);
+ void exponentiateX(long pow, byte[] output);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index ce02be4d..48753011 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -19,14 +19,23 @@ abstract class GCMUtil
return tmp;
}
+ static byte[] asBytes(int[] ns)
+ {
+ byte[] output = new byte[16];
+ Pack.intToBigEndian(ns, output, 0);
+ return output;
+ }
+
static int[] asInts(byte[] bs)
{
- int[] us = new int[4];
- us[0] = Pack.bigEndianToInt(bs, 0);
- us[1] = Pack.bigEndianToInt(bs, 4);
- us[2] = Pack.bigEndianToInt(bs, 8);
- us[3] = Pack.bigEndianToInt(bs, 12);
- return us;
+ int[] output = new int[4];
+ Pack.bigEndianToInt(bs, 0, output);
+ return output;
+ }
+
+ static void asInts(byte[] bs, int[] output)
+ {
+ Pack.bigEndianToInt(bs, 0, output);
}
static void multiply(byte[] block, byte[] val)
@@ -71,6 +80,17 @@ abstract class GCMUtil
}
}
+ static void multiplyP(int[] x, int[] output)
+ {
+ boolean lsb = (x[3] & 1) != 0;
+ shiftRight(x, output);
+ if (lsb)
+ {
+ output[0] ^= 0xe1000000;
+ }
+ }
+
+ // P is the value with only bit i=1 set
static void multiplyP8(int[] x)
{
// for (int i = 8; i != 0; --i)
@@ -89,6 +109,19 @@ abstract class GCMUtil
}
}
+ static void multiplyP8(int[] x, int[] output)
+ {
+ int lsw = x[3];
+ shiftRightN(x, 8, output);
+ for (int i = 7; i >= 0; --i)
+ {
+ if ((lsw & (1 << i)) != 0)
+ {
+ output[0] ^= (0xe1000000 >>> (7 - i));
+ }
+ }
+ }
+
static void shiftRight(byte[] block)
{
int i = 0;
@@ -105,6 +138,22 @@ abstract class GCMUtil
}
}
+ static void shiftRight(byte[] block, byte[] output)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ output[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+
static void shiftRight(int[] block)
{
int i = 0;
@@ -121,6 +170,22 @@ abstract class GCMUtil
}
}
+ static void shiftRight(int[] block, int[] output)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i];
+ output[i] = (b >>> 1) | bit;
+ if (++i == 4)
+ {
+ break;
+ }
+ bit = b << 31;
+ }
+ }
+
static void shiftRightN(int[] block, int n)
{
int i = 0;
@@ -137,6 +202,22 @@ abstract class GCMUtil
}
}
+ static void shiftRightN(int[] block, int n, int[] output)
+ {
+ int i = 0;
+ int bits = 0;
+ for (;;)
+ {
+ int b = block[i];
+ output[i] = (b >>> n) | bits;
+ if (++i == 4)
+ {
+ break;
+ }
+ bits = b << (32 - n);
+ }
+ }
+
static void xor(byte[] block, byte[] val)
{
for (int i = 15; i >= 0; --i)
@@ -145,6 +226,22 @@ abstract class GCMUtil
}
}
+ static void xor(byte[] block, byte[] val, int off, int len)
+ {
+ while (len-- > 0)
+ {
+ block[len] ^= val[off + len];
+ }
+ }
+
+ static void xor(byte[] block, byte[] val, byte[] output)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ output[i] = (byte)(block[i] ^ val[i]);
+ }
+ }
+
static void xor(int[] block, int[] val)
{
for (int i = 3; i >= 0; --i)
@@ -152,4 +249,12 @@ abstract class GCMUtil
block[i] ^= val[i];
}
}
+
+ static void xor(int[] block, int[] val, int[] output)
+ {
+ for (int i = 3; i >= 0; --i)
+ {
+ output[i] = block[i] ^ val[i];
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
new file mode 100644
index 00000000..a0512086
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
@@ -0,0 +1,57 @@
+package org.bouncycastle.crypto.modes.gcm;
+
+import java.util.Vector;
+
+import org.bouncycastle.util.Arrays;
+
+public class Tables1kGCMExponentiator implements GCMExponentiator
+{
+ // A lookup table of the power-of-two powers of 'x'
+ // - lookupPowX2[i] = x^(2^i)
+ private Vector lookupPowX2;
+
+ public void init(byte[] x)
+ {
+ if (lookupPowX2 != null && Arrays.areEqual(x, (byte[])lookupPowX2.elementAt(0)))
+ {
+ return;
+ }
+
+ lookupPowX2 = new Vector(8);
+ lookupPowX2.addElement(Arrays.clone(x));
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ byte[] y = GCMUtil.oneAsBytes();
+ int bit = 0;
+ while (pow > 0)
+ {
+ if ((pow & 1L) != 0)
+ {
+ ensureAvailable(bit);
+ GCMUtil.multiply(y, (byte[])lookupPowX2.elementAt(bit));
+ }
+ ++bit;
+ pow >>>= 1;
+ }
+
+ System.arraycopy(y, 0, output, 0, 16);
+ }
+
+ private void ensureAvailable(int bit)
+ {
+ int count = lookupPowX2.size();
+ if (count <= bit)
+ {
+ byte[] tmp = (byte[])lookupPowX2.elementAt(count - 1);
+ do
+ {
+ tmp = Arrays.clone(tmp);
+ GCMUtil.multiply(tmp, tmp);
+ lookupPowX2.addElement(tmp);
+ }
+ while (++count <= bit);
+ }
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
index 9d21cf0e..8535db5a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
@@ -1,41 +1,40 @@
package org.bouncycastle.crypto.modes.gcm;
import org.bouncycastle.crypto.util.Pack;
+import org.bouncycastle.util.Arrays;
-public class Tables8kGCMMultiplier implements GCMMultiplier
+public class Tables8kGCMMultiplier implements GCMMultiplier
{
- private final int[][][] M = new int[32][16][];
+ private byte[] H;
+ private int[][][] M;
public void init(byte[] H)
{
- M[0][0] = new int[4];
- M[1][0] = new int[4];
- M[1][8] = GCMUtil.asInts(H);
-
- for (int j = 4; j >= 1; j >>= 1)
+ if (M == null)
{
- int[] tmp = new int[4];
- System.arraycopy(M[1][j + j], 0, tmp, 0, 4);
-
- GCMUtil.multiplyP(tmp);
- M[1][j] = tmp;
+ M = new int[32][16][4];
}
-
+ else if (Arrays.areEqual(this.H, H))
{
- int[] tmp = new int[4];
- System.arraycopy(M[1][1], 0, tmp, 0, 4);
-
- GCMUtil.multiplyP(tmp);
- M[0][8] = tmp;
+ return;
}
+ this.H = Arrays.clone(H);
+
+ // M[0][0] is ZEROES;
+ // M[1][0] is ZEROES;
+ GCMUtil.asInts(H, M[1][8]);
+
for (int j = 4; j >= 1; j >>= 1)
{
- int[] tmp = new int[4];
- System.arraycopy(M[0][j + j], 0, tmp, 0, 4);
+ GCMUtil.multiplyP(M[1][j + j], M[1][j]);
+ }
+
+ GCMUtil.multiplyP(M[1][1], M[0][8]);
- GCMUtil.multiplyP(tmp);
- M[0][j] = tmp;
+ for (int j = 4; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[0][j + j], M[0][j]);
}
int i = 0;
@@ -45,11 +44,7 @@ public class Tables8kGCMMultiplier implements GCMMultiplier
{
for (int k = 1; k < j; ++k)
{
- int[] tmp = new int[4];
- System.arraycopy(M[i][j], 0, tmp, 0, 4);
-
- GCMUtil.xor(tmp, M[i][k]);
- M[i][j + k] = tmp;
+ GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
}
}
@@ -60,14 +55,10 @@ public class Tables8kGCMMultiplier implements GCMMultiplier
if (i > 1)
{
- M[i][0] = new int[4];
+ // M[i][0] is ZEROES;
for(int j = 8; j > 0; j >>= 1)
{
- int[] tmp = new int[4];
- System.arraycopy(M[i - 2][j], 0, tmp, 0, 4);
-
- GCMUtil.multiplyP8(tmp);
- M[i][j] = tmp;
+ GCMUtil.multiplyP8(M[i - 2][j], M[i][j]);
}
}
}
@@ -96,4 +87,4 @@ public class Tables8kGCMMultiplier implements GCMMultiplier
Pack.intToBigEndian(z, x, 0);
}
-}
+} \ No newline at end of file
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
index ec412b95..ee3fd60e 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
@@ -5,6 +5,7 @@ import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.params.ParametersWithRandom;
/**
@@ -191,7 +192,7 @@ public class PaddedBufferedBlockCipher
{
if ((outOff + length) > out.length)
{
- throw new DataLengthException("output buffer too short");
+ throw new OutputLengthException("output buffer too short");
}
}
@@ -254,7 +255,7 @@ public class PaddedBufferedBlockCipher
{
reset();
- throw new DataLengthException("output buffer too short");
+ throw new OutputLengthException("output buffer too short");
}
resultLen = cipher.processBlock(buf, 0, out, outOff);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
index b60ef400..9a9272ba 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/AEADParameters.java
@@ -16,7 +16,19 @@ public class AEADParameters
* @param key key to be used by underlying cipher
* @param macSize macSize in bits
* @param nonce nonce to be used
- * @param associatedText associated text, if any
+ */
+ public AEADParameters(KeyParameter key, int macSize, byte[] nonce)
+ {
+ this(key, macSize, nonce, null);
+ }
+
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ * @param associatedText initial associated text, if any
*/
public AEADParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
index 8ddfac85..394f2c2f 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java
@@ -6,10 +6,10 @@ import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
// BEGIN android-removed
// import org.bouncycastle.asn1.oiw.ElGamalParameter;
@@ -98,7 +98,7 @@ public class PrivateKeyFactory
else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
DHParameter params = DHParameter.getInstance(algId.getParameters());
- DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
BigInteger lVal = params.getL();
int l = lVal == null ? 0 : lVal.intValue();
@@ -110,7 +110,7 @@ public class PrivateKeyFactory
// else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
// ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
- // DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
+ // ASN1Integer = (ASN1Integer)keyInfo.parsePrivateKey();
//
// return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
// params.getP(), params.getG()));
@@ -118,7 +118,7 @@ public class PrivateKeyFactory
// END android-removed
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
{
- DERInteger derX = (DERInteger)keyInfo.parsePrivateKey();
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
ASN1Encodable de = algId.getParameters();
DSAParameters parameters = null;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
index 05520f0e..6a5c88e0 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java
@@ -6,11 +6,11 @@ import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
// BEGIN android-removed
@@ -133,7 +133,7 @@ public class PublicKeyFactory
else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
{
DHParameter params = DHParameter.getInstance(algId.getParameters());
- DERInteger derY = (DERInteger)keyInfo.parsePublicKey();
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
BigInteger lVal = params.getL();
int l = lVal == null ? 0 : lVal.intValue();
@@ -145,7 +145,7 @@ public class PublicKeyFactory
// else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
// {
// ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
- // DERInteger derY = (DERInteger)keyInfo.parsePublicKey();
+ // ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
//
// return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
// params.getP(), params.getG()));
@@ -154,7 +154,7 @@ public class PublicKeyFactory
else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
|| algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
{
- DERInteger derY = (DERInteger)keyInfo.parsePublicKey();
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
ASN1Encodable de = algId.getParameters();
DSAParameters parameters = null;