Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hook <dgh@cryptoworkshop.com>2013-05-17 03:53:06 +0400
committerDavid Hook <dgh@cryptoworkshop.com>2013-05-17 03:53:06 +0400
commit60653dba5719e4d60038194c6a4ca558558fe1dc (patch)
tree5d3fc31323fe0c0384953b733823f2b22d5936d9
parent26662a93f7283d426d325d472173f4369108375e (diff)
fixed line endings.
-rw-r--r--src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java84
-rw-r--r--src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java850
-rw-r--r--src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java782
-rw-r--r--src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java92
-rw-r--r--src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java370
-rw-r--r--src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java180
-rw-r--r--src/main/java/org/bouncycastle/bcpg/UserIDPacket.java78
-rw-r--r--src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java262
-rw-r--r--src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java148
-rwxr-xr-xsrc/main/java/org/bouncycastle/crypto/engines/IESEngine.java796
-rw-r--r--src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java284
-rw-r--r--src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java756
-rw-r--r--src/main/java/org/bouncycastle/crypto/util/Pack.java384
-rw-r--r--src/main/java/org/bouncycastle/math/ec/ECPoint.java1186
-rw-r--r--src/main/java/org/bouncycastle/util/encoders/Base64.java302
-rw-r--r--src/main/java/org/bouncycastle/util/encoders/Hex.java296
16 files changed, 3425 insertions, 3425 deletions
diff --git a/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
index 4d6df7a3..98f46a6d 100644
--- a/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+++ b/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
@@ -1,42 +1,42 @@
-package org.bouncycastle.asn1;
-
-public class ASN1ObjectIdentifier
- extends DERObjectIdentifier
-{
- public ASN1ObjectIdentifier(String identifier)
- {
- super(identifier);
- }
-
- ASN1ObjectIdentifier(byte[] bytes)
- {
- super(bytes);
- }
-
- ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
- {
- super(oid, branch);
- }
-
- /**
- * Return an OID that creates a branch under the current one.
- *
- * @param branchID node numbers for the new branch.
- * @return the OID for the new created branch.
- */
- public ASN1ObjectIdentifier branch(String branchID)
- {
- return new ASN1ObjectIdentifier(this, branchID);
- }
-
- /**
- * Return true if this oid is an extension of the passed in branch, stem.
- * @param stem the arc or branch that is a possible parent.
- * @return true if the branch is on the passed in stem, false otherwise.
- */
- public boolean on(ASN1ObjectIdentifier stem)
- {
- String id = getId(), stemId = stem.getId();
- return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
- }
-}
+package org.bouncycastle.asn1;
+
+public class ASN1ObjectIdentifier
+ extends DERObjectIdentifier
+{
+ public ASN1ObjectIdentifier(String identifier)
+ {
+ super(identifier);
+ }
+
+ ASN1ObjectIdentifier(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branch)
+ {
+ super(oid, branch);
+ }
+
+ /**
+ * Return an OID that creates a branch under the current one.
+ *
+ * @param branchID node numbers for the new branch.
+ * @return the OID for the new created branch.
+ */
+ public ASN1ObjectIdentifier branch(String branchID)
+ {
+ return new ASN1ObjectIdentifier(this, branchID);
+ }
+
+ /**
+ * Return true if this oid is an extension of the passed in branch, stem.
+ * @param stem the arc or branch that is a possible parent.
+ * @return true if the branch is on the passed in stem, false otherwise.
+ */
+ public boolean on(ASN1ObjectIdentifier stem)
+ {
+ String id = getId(), stemId = stem.getId();
+ return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java b/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
index 4f320b30..418f991b 100644
--- a/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ b/src/main/java/org/bouncycastle/asn1/DERObjectIdentifier.java
@@ -1,425 +1,425 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-public class DERObjectIdentifier
- extends ASN1Primitive
-{
- String identifier;
-
- private byte[] body;
-
- /**
- * return an OID from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1ObjectIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)obj;
- }
-
- if (obj instanceof DERObjectIdentifier)
- {
- return new ASN1ObjectIdentifier(((DERObjectIdentifier)obj).getId());
- }
-
- if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
- {
- return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
- }
-
- if (obj instanceof byte[])
- {
- return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Object Identifier from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1ObjectIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERObjectIdentifier)
- {
- return getInstance(o);
- }
- else
- {
- return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
- }
- }
-
- private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
-
- DERObjectIdentifier(
- byte[] bytes)
- {
- StringBuffer objId = new StringBuffer();
- long value = 0;
- BigInteger bigValue = null;
- boolean first = true;
-
- for (int i = 0; i != bytes.length; i++)
- {
- int b = bytes[i] & 0xff;
-
- if (value <= LONG_LIMIT)
- {
- value += (b & 0x7f);
- if ((b & 0x80) == 0) // end of number reached
- {
- if (first)
- {
- if (value < 40)
- {
- objId.append('0');
- }
- else if (value < 80)
- {
- objId.append('1');
- value -= 40;
- }
- else
- {
- objId.append('2');
- value -= 80;
- }
- first = false;
- }
-
- objId.append('.');
- objId.append(value);
- value = 0;
- }
- else
- {
- value <<= 7;
- }
- }
- else
- {
- if (bigValue == null)
- {
- bigValue = BigInteger.valueOf(value);
- }
- bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
- if ((b & 0x80) == 0)
- {
- if (first)
- {
- objId.append('2');
- bigValue = bigValue.subtract(BigInteger.valueOf(80));
- first = false;
- }
-
- objId.append('.');
- objId.append(bigValue);
- bigValue = null;
- value = 0;
- }
- else
- {
- bigValue = bigValue.shiftLeft(7);
- }
- }
- }
-
- this.identifier = objId.toString();
- this.body = Arrays.clone(bytes);
- }
-
- public DERObjectIdentifier(
- String identifier)
- {
- if (identifier == null)
- {
- throw new IllegalArgumentException("'identifier' cannot be null");
- }
- if (!isValidIdentifier(identifier))
- {
- throw new IllegalArgumentException("string " + identifier + " not an OID");
- }
-
- this.identifier = identifier;
- }
-
- DERObjectIdentifier(DERObjectIdentifier oid, String branchID)
- {
- if (!isValidBranchID(branchID, 0))
- {
- throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
- }
-
- this.identifier = oid.getId() + "." + branchID;
- }
-
- public String getId()
- {
- return identifier;
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- long fieldValue)
- {
- byte[] result = new byte[9];
- int pos = 8;
- result[pos] = (byte)((int)fieldValue & 0x7f);
- while (fieldValue >= (1L << 7))
- {
- fieldValue >>= 7;
- result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
- }
- out.write(result, pos, 9 - pos);
- }
-
- private void writeField(
- ByteArrayOutputStream out,
- BigInteger fieldValue)
- {
- int byteCount = (fieldValue.bitLength()+6)/7;
- if (byteCount == 0)
- {
- out.write(0);
- }
- else
- {
- BigInteger tmpValue = fieldValue;
- byte[] tmp = new byte[byteCount];
- for (int i = byteCount-1; i >= 0; i--)
- {
- tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
- tmpValue = tmpValue.shiftRight(7);
- }
- tmp[byteCount-1] &= 0x7f;
- out.write(tmp, 0, tmp.length);
- }
- }
-
- private void doOutput(ByteArrayOutputStream aOut)
- {
- OIDTokenizer tok = new OIDTokenizer(identifier);
- int first = Integer.parseInt(tok.nextToken()) * 40;
-
- String secondToken = tok.nextToken();
- if (secondToken.length() <= 18)
- {
- writeField(aOut, first + Long.parseLong(secondToken));
- }
- else
- {
- writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
- }
-
- while (tok.hasMoreTokens())
- {
- String token = tok.nextToken();
- if (token.length() <= 18)
- {
- writeField(aOut, Long.parseLong(token));
- }
- else
- {
- writeField(aOut, new BigInteger(token));
- }
- }
- }
-
- protected synchronized byte[] getBody()
- {
- if (body == null)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- doOutput(bOut);
-
- body = bOut.toByteArray();
- }
-
- return body;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- throws IOException
- {
- int length = getBody().length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- byte[] enc = getBody();
-
- out.write(BERTags.OBJECT_IDENTIFIER);
- out.writeLength(enc.length);
- out.write(enc);
- }
-
- public int hashCode()
- {
- return identifier.hashCode();
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERObjectIdentifier))
- {
- return false;
- }
-
- return identifier.equals(((DERObjectIdentifier)o).identifier);
- }
-
- public String toString()
- {
- return getId();
- }
-
- private static boolean isValidBranchID(
- String branchID, int start)
- {
- boolean periodAllowed = false;
-
- int pos = branchID.length();
- while (--pos >= start)
- {
- char ch = branchID.charAt(pos);
-
- // TODO Leading zeroes?
- if ('0' <= ch && ch <= '9')
- {
- periodAllowed = true;
- continue;
- }
-
- if (ch == '.')
- {
- if (!periodAllowed)
- {
- return false;
- }
-
- periodAllowed = false;
- continue;
- }
-
- return false;
- }
-
- return periodAllowed;
- }
-
- private static boolean isValidIdentifier(
- String identifier)
- {
- if (identifier.length() < 3 || identifier.charAt(1) != '.')
- {
- return false;
- }
-
- char first = identifier.charAt(0);
- if (first < '0' || first > '2')
- {
- return false;
- }
-
- return isValidBranchID(identifier, 2);
- }
-
- private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
-
- static ASN1ObjectIdentifier fromOctetString(byte[] enc)
- {
- if (enc.length < 3)
- {
- return new ASN1ObjectIdentifier(enc);
- }
-
- int idx1 = enc[enc.length - 2] & 0xff;
- // in this case top bit is always zero
- int idx2 = enc[enc.length - 1] & 0x7f;
-
- ASN1ObjectIdentifier possibleMatch;
-
- synchronized (cache)
- {
- ASN1ObjectIdentifier[] first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx1 = (idx1 + 1) & 0xff;
- first = cache[idx1];
- if (first == null)
- {
- first = cache[idx1] = new ASN1ObjectIdentifier[128];
- }
-
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- idx2 = (idx2 + 1) & 0x7f;
- possibleMatch = first[idx2];
- if (possibleMatch == null)
- {
- return first[idx2] = new ASN1ObjectIdentifier(enc);
- }
- }
-
- if (Arrays.areEqual(enc, possibleMatch.getBody()))
- {
- return possibleMatch;
- }
-
- return new ASN1ObjectIdentifier(enc);
- }
-}
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Arrays;
+
+public class DERObjectIdentifier
+ extends ASN1Primitive
+{
+ String identifier;
+
+ private byte[] body;
+
+ /**
+ * return an OID from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ if (obj instanceof DERObjectIdentifier)
+ {
+ return new ASN1ObjectIdentifier(((DERObjectIdentifier)obj).getId());
+ }
+
+ if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
+ }
+
+ if (obj instanceof byte[])
+ {
+ return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERObjectIdentifier)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
+
+ DERObjectIdentifier(
+ byte[] bytes)
+ {
+ StringBuffer objId = new StringBuffer();
+ long value = 0;
+ BigInteger bigValue = null;
+ boolean first = true;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ int b = bytes[i] & 0xff;
+
+ if (value <= LONG_LIMIT)
+ {
+ value += (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ if (value < 40)
+ {
+ objId.append('0');
+ }
+ else if (value < 80)
+ {
+ objId.append('1');
+ value -= 40;
+ }
+ else
+ {
+ objId.append('2');
+ value -= 80;
+ }
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(value);
+ value = 0;
+ }
+ else
+ {
+ value <<= 7;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.valueOf(value);
+ }
+ bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ if (first)
+ {
+ objId.append('2');
+ bigValue = bigValue.subtract(BigInteger.valueOf(80));
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ else
+ {
+ bigValue = bigValue.shiftLeft(7);
+ }
+ }
+ }
+
+ this.identifier = objId.toString();
+ this.body = Arrays.clone(bytes);
+ }
+
+ public DERObjectIdentifier(
+ String identifier)
+ {
+ if (identifier == null)
+ {
+ throw new IllegalArgumentException("'identifier' cannot be null");
+ }
+ if (!isValidIdentifier(identifier))
+ {
+ throw new IllegalArgumentException("string " + identifier + " not an OID");
+ }
+
+ this.identifier = identifier;
+ }
+
+ DERObjectIdentifier(DERObjectIdentifier oid, String branchID)
+ {
+ if (!isValidBranchID(branchID, 0))
+ {
+ throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
+ }
+
+ this.identifier = oid.getId() + "." + branchID;
+ }
+
+ public String getId()
+ {
+ return identifier;
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ long fieldValue)
+ {
+ byte[] result = new byte[9];
+ int pos = 8;
+ result[pos] = (byte)((int)fieldValue & 0x7f);
+ while (fieldValue >= (1L << 7))
+ {
+ fieldValue >>= 7;
+ result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
+ }
+ out.write(result, pos, 9 - pos);
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ BigInteger fieldValue)
+ {
+ int byteCount = (fieldValue.bitLength()+6)/7;
+ if (byteCount == 0)
+ {
+ out.write(0);
+ }
+ else
+ {
+ BigInteger tmpValue = fieldValue;
+ byte[] tmp = new byte[byteCount];
+ for (int i = byteCount-1; i >= 0; i--)
+ {
+ tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
+ tmpValue = tmpValue.shiftRight(7);
+ }
+ tmp[byteCount-1] &= 0x7f;
+ out.write(tmp, 0, tmp.length);
+ }
+ }
+
+ private void doOutput(ByteArrayOutputStream aOut)
+ {
+ OIDTokenizer tok = new OIDTokenizer(identifier);
+ int first = Integer.parseInt(tok.nextToken()) * 40;
+
+ String secondToken = tok.nextToken();
+ if (secondToken.length() <= 18)
+ {
+ writeField(aOut, first + Long.parseLong(secondToken));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
+ }
+
+ while (tok.hasMoreTokens())
+ {
+ String token = tok.nextToken();
+ if (token.length() <= 18)
+ {
+ writeField(aOut, Long.parseLong(token));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(token));
+ }
+ }
+ }
+
+ protected synchronized byte[] getBody()
+ {
+ if (body == null)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ doOutput(bOut);
+
+ body = bOut.toByteArray();
+ }
+
+ return body;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBody().length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] enc = getBody();
+
+ out.write(BERTags.OBJECT_IDENTIFIER);
+ out.writeLength(enc.length);
+ out.write(enc);
+ }
+
+ public int hashCode()
+ {
+ return identifier.hashCode();
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERObjectIdentifier))
+ {
+ return false;
+ }
+
+ return identifier.equals(((DERObjectIdentifier)o).identifier);
+ }
+
+ public String toString()
+ {
+ return getId();
+ }
+
+ private static boolean isValidBranchID(
+ String branchID, int start)
+ {
+ boolean periodAllowed = false;
+
+ int pos = branchID.length();
+ while (--pos >= start)
+ {
+ char ch = branchID.charAt(pos);
+
+ // TODO Leading zeroes?
+ if ('0' <= ch && ch <= '9')
+ {
+ periodAllowed = true;
+ continue;
+ }
+
+ if (ch == '.')
+ {
+ if (!periodAllowed)
+ {
+ return false;
+ }
+
+ periodAllowed = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return periodAllowed;
+ }
+
+ private static boolean isValidIdentifier(
+ String identifier)
+ {
+ if (identifier.length() < 3 || identifier.charAt(1) != '.')
+ {
+ return false;
+ }
+
+ char first = identifier.charAt(0);
+ if (first < '0' || first > '2')
+ {
+ return false;
+ }
+
+ return isValidBranchID(identifier, 2);
+ }
+
+ private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
+
+ static ASN1ObjectIdentifier fromOctetString(byte[] enc)
+ {
+ if (enc.length < 3)
+ {
+ return new ASN1ObjectIdentifier(enc);
+ }
+
+ int idx1 = enc[enc.length - 2] & 0xff;
+ // in this case top bit is always zero
+ int idx2 = enc[enc.length - 1] & 0x7f;
+
+ ASN1ObjectIdentifier possibleMatch;
+
+ synchronized (cache)
+ {
+ ASN1ObjectIdentifier[] first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx1 = (idx1 + 1) & 0xff;
+ first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx2 = (idx2 + 1) & 0x7f;
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ return new ASN1ObjectIdentifier(enc);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java b/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
index 86873cec..1e2e0723 100644
--- a/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
+++ b/src/main/java/org/bouncycastle/bcpg/BCPGInputStream.java
@@ -1,391 +1,391 @@
-package org.bouncycastle.bcpg;
-
-import org.bouncycastle.util.io.Streams;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * reader for PGP objects
- */
-public class BCPGInputStream
- extends InputStream implements PacketTags
-{
- InputStream in;
- boolean next = false;
- int nextB;
-
- public BCPGInputStream(
- InputStream in)
- {
- this.in = in;
- }
-
- public int available()
- throws IOException
- {
- return in.available();
- }
-
- public int read()
- throws IOException
- {
- if (next)
- {
- next = false;
-
- return nextB;
- }
- else
- {
- return in.read();
- }
- }
-
- public int read(
- byte[] buf,
- int off,
- int len)
- throws IOException
- {
- if (len == 0)
- {
- return 0;
- }
-
- if (!next)
- {
- return in.read(buf, off, len);
- }
-
- // We have next byte waiting, so return it
-
- if (nextB < 0)
- {
- return -1; // EOF
- }
-
- buf[off] = (byte)nextB; // May throw NullPointerException...
- next = false; // ...so only set this afterwards
-
- return 1;
- }
-
- public void readFully(
- byte[] buf,
- int off,
- int len)
- throws IOException
- {
- if (Streams.readFully(this, buf, off, len) < len)
- {
- throw new EOFException();
- }
- }
-
- public byte[] readAll()
- throws IOException
- {
- return Streams.readAll(this);
- }
-
- public void readFully(
- byte[] buf)
- throws IOException
- {
- readFully(buf, 0, buf.length);
- }
-
- /**
- * returns the next packet tag in the stream.
- *
- * @return the tag number.
- *
- * @throws IOException
- */
- public int nextPacketTag()
- throws IOException
- {
- if (!next)
- {
- try
- {
- nextB = in.read();
- }
- catch (EOFException e)
- {
- nextB = -1;
- }
- }
-
- next = true;
-
- if (nextB >= 0)
- {
- if ((nextB & 0x40) != 0) // new
- {
- return (nextB & 0x3f);
- }
- else // old
- {
- return ((nextB & 0x3f) >> 2);
- }
- }
-
- return nextB;
- }
-
- public Packet readPacket()
- throws IOException
- {
- int hdr = this.read();
-
- if (hdr < 0)
- {
- return null;
- }
-
- if ((hdr & 0x80) == 0)
- {
- throw new IOException("invalid header encountered");
- }
-
- boolean newPacket = (hdr & 0x40) != 0;
- int tag = 0;
- int bodyLen = 0;
- boolean partial = false;
-
- if (newPacket)
- {
- tag = hdr & 0x3f;
-
- int l = this.read();
-
- if (l < 192)
- {
- bodyLen = l;
- }
- else if (l <= 223)
- {
- int b = in.read();
-
- bodyLen = ((l - 192) << 8) + (b) + 192;
- }
- else if (l == 255)
- {
- bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
- }
- else
- {
- partial = true;
- bodyLen = 1 << (l & 0x1f);
- }
- }
- else
- {
- int lengthType = hdr & 0x3;
-
- tag = (hdr & 0x3f) >> 2;
-
- switch (lengthType)
- {
- case 0:
- bodyLen = this.read();
- break;
- case 1:
- bodyLen = (this.read() << 8) | this.read();
- break;
- case 2:
- bodyLen = (this.read() << 24) | (this.read() << 16) | (this.read() << 8) | this.read();
- break;
- case 3:
- partial = true;
- break;
- default:
- throw new IOException("unknown length type encountered");
- }
- }
-
- BCPGInputStream objStream;
-
- if (bodyLen == 0 && partial)
- {
- objStream = this;
- }
- else
- {
- objStream = new BCPGInputStream(new PartialInputStream(this, partial, bodyLen));
- }
-
- switch (tag)
- {
- case RESERVED:
- return new InputStreamPacket(objStream);
- case PUBLIC_KEY_ENC_SESSION:
- return new PublicKeyEncSessionPacket(objStream);
- case SIGNATURE:
- return new SignaturePacket(objStream);
- case SYMMETRIC_KEY_ENC_SESSION:
- return new SymmetricKeyEncSessionPacket(objStream);
- case ONE_PASS_SIGNATURE:
- return new OnePassSignaturePacket(objStream);
- case SECRET_KEY:
- return new SecretKeyPacket(objStream);
- case PUBLIC_KEY:
- return new PublicKeyPacket(objStream);
- case SECRET_SUBKEY:
- return new SecretSubkeyPacket(objStream);
- case COMPRESSED_DATA:
- return new CompressedDataPacket(objStream);
- case SYMMETRIC_KEY_ENC:
- return new SymmetricEncDataPacket(objStream);
- case MARKER:
- return new MarkerPacket(objStream);
- case LITERAL_DATA:
- return new LiteralDataPacket(objStream);
- case TRUST:
- return new TrustPacket(objStream);
- case USER_ID:
- return new UserIDPacket(objStream);
- case USER_ATTRIBUTE:
- return new UserAttributePacket(objStream);
- case PUBLIC_SUBKEY:
- return new PublicSubkeyPacket(objStream);
- case SYM_ENC_INTEGRITY_PRO:
- return new SymmetricEncIntegrityPacket(objStream);
- case MOD_DETECTION_CODE:
- return new ModDetectionCodePacket(objStream);
- case EXPERIMENTAL_1:
- case EXPERIMENTAL_2:
- case EXPERIMENTAL_3:
- case EXPERIMENTAL_4:
- return new ExperimentalPacket(tag, objStream);
- default:
- throw new IOException("unknown packet type encountered: " + tag);
- }
- }
-
- public void close()
- throws IOException
- {
- in.close();
- }
-
- /**
- * a stream that overlays our input stream, allowing the user to only read a segment of it.
- *
- * NB: dataLength will be negative if the segment length is in the upper range above 2**31.
- */
- private static class PartialInputStream
- extends InputStream
- {
- private BCPGInputStream in;
- private boolean partial;
- private int dataLength;
-
- PartialInputStream(
- BCPGInputStream in,
- boolean partial,
- int dataLength)
- {
- this.in = in;
- this.partial = partial;
- this.dataLength = dataLength;
- }
-
- public int available()
- throws IOException
- {
- int avail = in.available();
-
- if (avail <= dataLength || dataLength < 0)
- {
- return avail;
- }
- else
- {
- if (partial && dataLength == 0)
- {
- return 1;
- }
- return dataLength;
- }
- }
-
- private int loadDataLength()
- throws IOException
- {
- int l = in.read();
-
- if (l < 0)
- {
- return -1;
- }
-
- partial = false;
- if (l < 192)
- {
- dataLength = l;
- }
- else if (l <= 223)
- {
- dataLength = ((l - 192) << 8) + (in.read()) + 192;
- }
- else if (l == 255)
- {
- dataLength = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
- }
- else
- {
- partial = true;
- dataLength = 1 << (l & 0x1f);
- }
-
- return dataLength;
- }
-
- public int read(byte[] buf, int offset, int len)
- throws IOException
- {
- do
- {
- if (dataLength != 0)
- {
- int readLen = (dataLength > len || dataLength < 0) ? len : dataLength;
- readLen = in.read(buf, offset, readLen);
- if (readLen < 0)
- {
- throw new EOFException("premature end of stream in PartialInputStream");
- }
- dataLength -= readLen;
- return readLen;
- }
- }
- while (partial && loadDataLength() >= 0);
-
- return -1;
- }
-
- public int read()
- throws IOException
- {
- do
- {
- if (dataLength != 0)
- {
- int ch = in.read();
- if (ch < 0)
- {
- throw new EOFException("premature end of stream in PartialInputStream");
- }
- dataLength--;
- return ch;
- }
- }
- while (partial && loadDataLength() >= 0);
-
- return -1;
- }
- }
-}
+package org.bouncycastle.bcpg;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.util.io.Streams;
+
+/**
+ * reader for PGP objects
+ */
+public class BCPGInputStream
+ extends InputStream implements PacketTags
+{
+ InputStream in;
+ boolean next = false;
+ int nextB;
+
+ public BCPGInputStream(
+ InputStream in)
+ {
+ this.in = in;
+ }
+
+ public int available()
+ throws IOException
+ {
+ return in.available();
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (next)
+ {
+ next = false;
+
+ return nextB;
+ }
+ else
+ {
+ return in.read();
+ }
+ }
+
+ public int read(
+ byte[] buf,
+ int off,
+ int len)
+ throws IOException
+ {
+ if (len == 0)
+ {
+ return 0;
+ }
+
+ if (!next)
+ {
+ return in.read(buf, off, len);
+ }
+
+ // We have next byte waiting, so return it
+
+ if (nextB < 0)
+ {
+ return -1; // EOF
+ }
+
+ buf[off] = (byte)nextB; // May throw NullPointerException...
+ next = false; // ...so only set this afterwards
+
+ return 1;
+ }
+
+ public void readFully(
+ byte[] buf,
+ int off,
+ int len)
+ throws IOException
+ {
+ if (Streams.readFully(this, buf, off, len) < len)
+ {
+ throw new EOFException();
+ }
+ }
+
+ public byte[] readAll()
+ throws IOException
+ {
+ return Streams.readAll(this);
+ }
+
+ public void readFully(
+ byte[] buf)
+ throws IOException
+ {
+ readFully(buf, 0, buf.length);
+ }
+
+ /**
+ * returns the next packet tag in the stream.
+ *
+ * @return the tag number.
+ *
+ * @throws IOException
+ */
+ public int nextPacketTag()
+ throws IOException
+ {
+ if (!next)
+ {
+ try
+ {
+ nextB = in.read();
+ }
+ catch (EOFException e)
+ {
+ nextB = -1;
+ }
+ }
+
+ next = true;
+
+ if (nextB >= 0)
+ {
+ if ((nextB & 0x40) != 0) // new
+ {
+ return (nextB & 0x3f);
+ }
+ else // old
+ {
+ return ((nextB & 0x3f) >> 2);
+ }
+ }
+
+ return nextB;
+ }
+
+ public Packet readPacket()
+ throws IOException
+ {
+ int hdr = this.read();
+
+ if (hdr < 0)
+ {
+ return null;
+ }
+
+ if ((hdr & 0x80) == 0)
+ {
+ throw new IOException("invalid header encountered");
+ }
+
+ boolean newPacket = (hdr & 0x40) != 0;
+ int tag = 0;
+ int bodyLen = 0;
+ boolean partial = false;
+
+ if (newPacket)
+ {
+ tag = hdr & 0x3f;
+
+ int l = this.read();
+
+ if (l < 192)
+ {
+ bodyLen = l;
+ }
+ else if (l <= 223)
+ {
+ int b = in.read();
+
+ bodyLen = ((l - 192) << 8) + (b) + 192;
+ }
+ else if (l == 255)
+ {
+ bodyLen = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
+ }
+ else
+ {
+ partial = true;
+ bodyLen = 1 << (l & 0x1f);
+ }
+ }
+ else
+ {
+ int lengthType = hdr & 0x3;
+
+ tag = (hdr & 0x3f) >> 2;
+
+ switch (lengthType)
+ {
+ case 0:
+ bodyLen = this.read();
+ break;
+ case 1:
+ bodyLen = (this.read() << 8) | this.read();
+ break;
+ case 2:
+ bodyLen = (this.read() << 24) | (this.read() << 16) | (this.read() << 8) | this.read();
+ break;
+ case 3:
+ partial = true;
+ break;
+ default:
+ throw new IOException("unknown length type encountered");
+ }
+ }
+
+ BCPGInputStream objStream;
+
+ if (bodyLen == 0 && partial)
+ {
+ objStream = this;
+ }
+ else
+ {
+ objStream = new BCPGInputStream(new PartialInputStream(this, partial, bodyLen));
+ }
+
+ switch (tag)
+ {
+ case RESERVED:
+ return new InputStreamPacket(objStream);
+ case PUBLIC_KEY_ENC_SESSION:
+ return new PublicKeyEncSessionPacket(objStream);
+ case SIGNATURE:
+ return new SignaturePacket(objStream);
+ case SYMMETRIC_KEY_ENC_SESSION:
+ return new SymmetricKeyEncSessionPacket(objStream);
+ case ONE_PASS_SIGNATURE:
+ return new OnePassSignaturePacket(objStream);
+ case SECRET_KEY:
+ return new SecretKeyPacket(objStream);
+ case PUBLIC_KEY:
+ return new PublicKeyPacket(objStream);
+ case SECRET_SUBKEY:
+ return new SecretSubkeyPacket(objStream);
+ case COMPRESSED_DATA:
+ return new CompressedDataPacket(objStream);
+ case SYMMETRIC_KEY_ENC:
+ return new SymmetricEncDataPacket(objStream);
+ case MARKER:
+ return new MarkerPacket(objStream);
+ case LITERAL_DATA:
+ return new LiteralDataPacket(objStream);
+ case TRUST:
+ return new TrustPacket(objStream);
+ case USER_ID:
+ return new UserIDPacket(objStream);
+ case USER_ATTRIBUTE:
+ return new UserAttributePacket(objStream);
+ case PUBLIC_SUBKEY:
+ return new PublicSubkeyPacket(objStream);
+ case SYM_ENC_INTEGRITY_PRO:
+ return new SymmetricEncIntegrityPacket(objStream);
+ case MOD_DETECTION_CODE:
+ return new ModDetectionCodePacket(objStream);
+ case EXPERIMENTAL_1:
+ case EXPERIMENTAL_2:
+ case EXPERIMENTAL_3:
+ case EXPERIMENTAL_4:
+ return new ExperimentalPacket(tag, objStream);
+ default:
+ throw new IOException("unknown packet type encountered: " + tag);
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ in.close();
+ }
+
+ /**
+ * a stream that overlays our input stream, allowing the user to only read a segment of it.
+ *
+ * NB: dataLength will be negative if the segment length is in the upper range above 2**31.
+ */
+ private static class PartialInputStream
+ extends InputStream
+ {
+ private BCPGInputStream in;
+ private boolean partial;
+ private int dataLength;
+
+ PartialInputStream(
+ BCPGInputStream in,
+ boolean partial,
+ int dataLength)
+ {
+ this.in = in;
+ this.partial = partial;
+ this.dataLength = dataLength;
+ }
+
+ public int available()
+ throws IOException
+ {
+ int avail = in.available();
+
+ if (avail <= dataLength || dataLength < 0)
+ {
+ return avail;
+ }
+ else
+ {
+ if (partial && dataLength == 0)
+ {
+ return 1;
+ }
+ return dataLength;
+ }
+ }
+
+ private int loadDataLength()
+ throws IOException
+ {
+ int l = in.read();
+
+ if (l < 0)
+ {
+ return -1;
+ }
+
+ partial = false;
+ if (l < 192)
+ {
+ dataLength = l;
+ }
+ else if (l <= 223)
+ {
+ dataLength = ((l - 192) << 8) + (in.read()) + 192;
+ }
+ else if (l == 255)
+ {
+ dataLength = (in.read() << 24) | (in.read() << 16) | (in.read() << 8) | in.read();
+ }
+ else
+ {
+ partial = true;
+ dataLength = 1 << (l & 0x1f);
+ }
+
+ return dataLength;
+ }
+
+ public int read(byte[] buf, int offset, int len)
+ throws IOException
+ {
+ do
+ {
+ if (dataLength != 0)
+ {
+ int readLen = (dataLength > len || dataLength < 0) ? len : dataLength;
+ readLen = in.read(buf, offset, readLen);
+ if (readLen < 0)
+ {
+ throw new EOFException("premature end of stream in PartialInputStream");
+ }
+ dataLength -= readLen;
+ return readLen;
+ }
+ }
+ while (partial && loadDataLength() >= 0);
+
+ return -1;
+ }
+
+ public int read()
+ throws IOException
+ {
+ do
+ {
+ if (dataLength != 0)
+ {
+ int ch = in.read();
+ if (ch < 0)
+ {
+ throw new EOFException("premature end of stream in PartialInputStream");
+ }
+ dataLength--;
+ return ch;
+ }
+ }
+ while (partial && loadDataLength() >= 0);
+
+ return -1;
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java b/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
index e3b0456a..8407052b 100644
--- a/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
+++ b/src/main/java/org/bouncycastle/bcpg/ExperimentalPacket.java
@@ -1,46 +1,46 @@
-package org.bouncycastle.bcpg;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * basic packet for an experimental packet.
- */
-public class ExperimentalPacket
- extends ContainedPacket implements PublicKeyAlgorithmTags
-{
- private int tag;
- private byte[] contents;
-
- /**
- *
- * @param in
- * @throws IOException
- */
- ExperimentalPacket(
- int tag,
- BCPGInputStream in)
- throws IOException
- {
- this.tag = tag;
- this.contents = in.readAll();
- }
-
- public int getTag()
- {
- return tag;
- }
-
- public byte[] getContents()
- {
- return Arrays.clone(contents);
- }
-
- public void encode(
- BCPGOutputStream out)
- throws IOException
- {
- out.writePacket(tag, contents, true);
- }
-}
+package org.bouncycastle.bcpg;
+
+import java.io.IOException;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * basic packet for an experimental packet.
+ */
+public class ExperimentalPacket
+ extends ContainedPacket implements PublicKeyAlgorithmTags
+{
+ private int tag;
+ private byte[] contents;
+
+ /**
+ *
+ * @param in
+ * @throws IOException
+ */
+ ExperimentalPacket(
+ int tag,
+ BCPGInputStream in)
+ throws IOException
+ {
+ this.tag = tag;
+ this.contents = in.readAll();
+ }
+
+ public int getTag()
+ {
+ return tag;
+ }
+
+ public byte[] getContents()
+ {
+ return Arrays.clone(contents);
+ }
+
+ public void encode(
+ BCPGOutputStream out)
+ throws IOException
+ {
+ out.writePacket(tag, contents, true);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java b/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
index 6be9632a..d362bb93 100644
--- a/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
+++ b/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java
@@ -1,185 +1,185 @@
-package org.bouncycastle.bcpg;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * basic packet for a PGP secret key
- */
-public class SecretKeyPacket
- extends ContainedPacket implements PublicKeyAlgorithmTags
-{
- public static final int USAGE_NONE = 0x00;
- public static final int USAGE_CHECKSUM = 0xff;
- public static final int USAGE_SHA1 = 0xfe;
-
- private PublicKeyPacket pubKeyPacket;
- private byte[] secKeyData;
- private int s2kUsage;
- private int encAlgorithm;
- private S2K s2k;
- private byte[] iv;
-
- /**
- *
- * @param in
- * @throws IOException
- */
- SecretKeyPacket(
- BCPGInputStream in)
- throws IOException
- {
- if (this instanceof SecretSubkeyPacket)
- {
- pubKeyPacket = new PublicSubkeyPacket(in);
- }
- else
- {
- pubKeyPacket = new PublicKeyPacket(in);
- }
-
- s2kUsage = in.read();
-
- if (s2kUsage == USAGE_CHECKSUM || s2kUsage == USAGE_SHA1)
- {
- encAlgorithm = in.read();
- s2k = new S2K(in);
- }
- else
- {
- encAlgorithm = s2kUsage;
- }
-
- if (!(s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K && s2k.getProtectionMode() == 0x01))
- {
- if (s2kUsage != 0)
- {
- if (encAlgorithm < 7)
- {
- iv = new byte[8];
- }
- else
- {
- iv = new byte[16];
- }
- in.readFully(iv, 0, iv.length);
- }
- }
-
- this.secKeyData = in.readAll();
- }
-
- /**
- *
- * @param pubKeyPacket
- * @param encAlgorithm
- * @param s2k
- * @param iv
- * @param secKeyData
- */
- public SecretKeyPacket(
- PublicKeyPacket pubKeyPacket,
- int encAlgorithm,
- S2K s2k,
- byte[] iv,
- byte[] secKeyData)
- {
- this.pubKeyPacket = pubKeyPacket;
- this.encAlgorithm = encAlgorithm;
-
- if (encAlgorithm != SymmetricKeyAlgorithmTags.NULL)
- {
- this.s2kUsage = USAGE_CHECKSUM;
- }
- else
- {
- this.s2kUsage = USAGE_NONE;
- }
-
- this.s2k = s2k;
- this.iv = iv;
- this.secKeyData = secKeyData;
- }
-
- public SecretKeyPacket(
- PublicKeyPacket pubKeyPacket,
- int encAlgorithm,
- int s2kUsage,
- S2K s2k,
- byte[] iv,
- byte[] secKeyData)
- {
- this.pubKeyPacket = pubKeyPacket;
- this.encAlgorithm = encAlgorithm;
- this.s2kUsage = s2kUsage;
- this.s2k = s2k;
- this.iv = iv;
- this.secKeyData = secKeyData;
- }
-
- public int getEncAlgorithm()
- {
- return encAlgorithm;
- }
-
- public int getS2KUsage()
- {
- return s2kUsage;
- }
-
- public byte[] getIV()
- {
- return iv;
- }
-
- public S2K getS2K()
- {
- return s2k;
- }
-
- public PublicKeyPacket getPublicKeyPacket()
- {
- return pubKeyPacket;
- }
-
- public byte[] getSecretKeyData()
- {
- return secKeyData;
- }
-
- public byte[] getEncodedContents()
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BCPGOutputStream pOut = new BCPGOutputStream(bOut);
-
- pOut.write(pubKeyPacket.getEncodedContents());
-
- pOut.write(s2kUsage);
-
- if (s2kUsage == USAGE_CHECKSUM || s2kUsage == USAGE_SHA1)
- {
- pOut.write(encAlgorithm);
- pOut.writeObject(s2k);
- }
-
- if (iv != null)
- {
- pOut.write(iv);
- }
-
- if (secKeyData != null && secKeyData.length > 0)
- {
- pOut.write(secKeyData);
- }
-
- return bOut.toByteArray();
- }
-
- public void encode(
- BCPGOutputStream out)
- throws IOException
- {
- out.writePacket(SECRET_KEY, getEncodedContents(), true);
- }
-}
+package org.bouncycastle.bcpg;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * basic packet for a PGP secret key
+ */
+public class SecretKeyPacket
+ extends ContainedPacket implements PublicKeyAlgorithmTags
+{
+ public static final int USAGE_NONE = 0x00;
+ public static final int USAGE_CHECKSUM = 0xff;
+ public static final int USAGE_SHA1 = 0xfe;
+
+ private PublicKeyPacket pubKeyPacket;
+ private byte[] secKeyData;
+ private int s2kUsage;
+ private int encAlgorithm;
+ private S2K s2k;
+ private byte[] iv;
+
+ /**
+ *
+ * @param in
+ * @throws IOException
+ */
+ SecretKeyPacket(
+ BCPGInputStream in)
+ throws IOException
+ {
+ if (this instanceof SecretSubkeyPacket)
+ {
+ pubKeyPacket = new PublicSubkeyPacket(in);
+ }
+ else
+ {
+ pubKeyPacket = new PublicKeyPacket(in);
+ }
+
+ s2kUsage = in.read();
+
+ if (s2kUsage == USAGE_CHECKSUM || s2kUsage == USAGE_SHA1)
+ {
+ encAlgorithm = in.read();
+ s2k = new S2K(in);
+ }
+ else
+ {
+ encAlgorithm = s2kUsage;
+ }
+
+ if (!(s2k != null && s2k.getType() == S2K.GNU_DUMMY_S2K && s2k.getProtectionMode() == 0x01))
+ {
+ if (s2kUsage != 0)
+ {
+ if (encAlgorithm < 7)
+ {
+ iv = new byte[8];
+ }
+ else
+ {
+ iv = new byte[16];
+ }
+ in.readFully(iv, 0, iv.length);
+ }
+ }
+
+ this.secKeyData = in.readAll();
+ }
+
+ /**
+ *
+ * @param pubKeyPacket
+ * @param encAlgorithm
+ * @param s2k
+ * @param iv
+ * @param secKeyData
+ */
+ public SecretKeyPacket(
+ PublicKeyPacket pubKeyPacket,
+ int encAlgorithm,
+ S2K s2k,
+ byte[] iv,
+ byte[] secKeyData)
+ {
+ this.pubKeyPacket = pubKeyPacket;
+ this.encAlgorithm = encAlgorithm;
+
+ if (encAlgorithm != SymmetricKeyAlgorithmTags.NULL)
+ {
+ this.s2kUsage = USAGE_CHECKSUM;
+ }
+ else
+ {
+ this.s2kUsage = USAGE_NONE;
+ }
+
+ this.s2k = s2k;
+ this.iv = iv;
+ this.secKeyData = secKeyData;
+ }
+
+ public SecretKeyPacket(
+ PublicKeyPacket pubKeyPacket,
+ int encAlgorithm,
+ int s2kUsage,
+ S2K s2k,
+ byte[] iv,
+ byte[] secKeyData)
+ {
+ this.pubKeyPacket = pubKeyPacket;
+ this.encAlgorithm = encAlgorithm;
+ this.s2kUsage = s2kUsage;
+ this.s2k = s2k;
+ this.iv = iv;
+ this.secKeyData = secKeyData;
+ }
+
+ public int getEncAlgorithm()
+ {
+ return encAlgorithm;
+ }
+
+ public int getS2KUsage()
+ {
+ return s2kUsage;
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ public S2K getS2K()
+ {
+ return s2k;
+ }
+
+ public PublicKeyPacket getPublicKeyPacket()
+ {
+ return pubKeyPacket;
+ }
+
+ public byte[] getSecretKeyData()
+ {
+ return secKeyData;
+ }
+
+ public byte[] getEncodedContents()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut);
+
+ pOut.write(pubKeyPacket.getEncodedContents());
+
+ pOut.write(s2kUsage);
+
+ if (s2kUsage == USAGE_CHECKSUM || s2kUsage == USAGE_SHA1)
+ {
+ pOut.write(encAlgorithm);
+ pOut.writeObject(s2k);
+ }
+
+ if (iv != null)
+ {
+ pOut.write(iv);
+ }
+
+ if (secKeyData != null && secKeyData.length > 0)
+ {
+ pOut.write(secKeyData);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ public void encode(
+ BCPGOutputStream out)
+ throws IOException
+ {
+ out.writePacket(SECRET_KEY, getEncodedContents(), true);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java b/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
index 3e4218fe..37769fef 100644
--- a/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
+++ b/src/main/java/org/bouncycastle/bcpg/SymmetricKeyEncSessionPacket.java
@@ -1,90 +1,90 @@
-package org.bouncycastle.bcpg;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Basic type for a symmetric encrypted session key packet
- */
-public class SymmetricKeyEncSessionPacket
- extends ContainedPacket
-{
- private int version;
- private int encAlgorithm;
- private S2K s2k;
- private byte[] secKeyData;
-
- public SymmetricKeyEncSessionPacket(
- BCPGInputStream in)
- throws IOException
- {
- version = in.read();
- encAlgorithm = in.read();
-
- s2k = new S2K(in);
-
- this.secKeyData = in.readAll();
- }
-
- public SymmetricKeyEncSessionPacket(
- int encAlgorithm,
- S2K s2k,
- byte[] secKeyData)
- {
- this.version = 4;
- this.encAlgorithm = encAlgorithm;
- this.s2k = s2k;
- this.secKeyData = secKeyData;
- }
-
- /**
- * @return int
- */
- public int getEncAlgorithm()
- {
- return encAlgorithm;
- }
-
- /**
- * @return S2K
- */
- public S2K getS2K()
- {
- return s2k;
- }
-
- /**
- * @return byte[]
- */
- public byte[] getSecKeyData()
- {
- return secKeyData;
- }
-
- /**
- * @return int
- */
- public int getVersion()
- {
- return version;
- }
-
- public void encode(
- BCPGOutputStream out)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- BCPGOutputStream pOut = new BCPGOutputStream(bOut);
-
- pOut.write(version);
- pOut.write(encAlgorithm);
- pOut.writeObject(s2k);
-
- if (secKeyData != null && secKeyData.length > 0)
- {
- pOut.write(secKeyData);
- }
-
- out.writePacket(SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray(), true);
- }
-}
+package org.bouncycastle.bcpg;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Basic type for a symmetric encrypted session key packet
+ */
+public class SymmetricKeyEncSessionPacket
+ extends ContainedPacket
+{
+ private int version;
+ private int encAlgorithm;
+ private S2K s2k;
+ private byte[] secKeyData;
+
+ public SymmetricKeyEncSessionPacket(
+ BCPGInputStream in)
+ throws IOException
+ {
+ version = in.read();
+ encAlgorithm = in.read();
+
+ s2k = new S2K(in);
+
+ this.secKeyData = in.readAll();
+ }
+
+ public SymmetricKeyEncSessionPacket(
+ int encAlgorithm,
+ S2K s2k,
+ byte[] secKeyData)
+ {
+ this.version = 4;
+ this.encAlgorithm = encAlgorithm;
+ this.s2k = s2k;
+ this.secKeyData = secKeyData;
+ }
+
+ /**
+ * @return int
+ */
+ public int getEncAlgorithm()
+ {
+ return encAlgorithm;
+ }
+
+ /**
+ * @return S2K
+ */
+ public S2K getS2K()
+ {
+ return s2k;
+ }
+
+ /**
+ * @return byte[]
+ */
+ public byte[] getSecKeyData()
+ {
+ return secKeyData;
+ }
+
+ /**
+ * @return int
+ */
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public void encode(
+ BCPGOutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ BCPGOutputStream pOut = new BCPGOutputStream(bOut);
+
+ pOut.write(version);
+ pOut.write(encAlgorithm);
+ pOut.writeObject(s2k);
+
+ if (secKeyData != null && secKeyData.length > 0)
+ {
+ pOut.write(secKeyData);
+ }
+
+ out.writePacket(SYMMETRIC_KEY_ENC_SESSION, bOut.toByteArray(), true);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java b/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
index dff7e5ab..15ae71b1 100644
--- a/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
+++ b/src/main/java/org/bouncycastle/bcpg/UserIDPacket.java
@@ -1,39 +1,39 @@
-package org.bouncycastle.bcpg;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Strings;
-
-/**
- * Basic type for a user ID packet.
- */
-public class UserIDPacket
- extends ContainedPacket
-{
- private byte[] idData;
-
- public UserIDPacket(
- BCPGInputStream in)
- throws IOException
- {
- this.idData = in.readAll();
- }
-
- public UserIDPacket(
- String id)
- {
- this.idData = Strings.toUTF8ByteArray(id);
- }
-
- public String getID()
- {
- return Strings.fromUTF8ByteArray(idData);
- }
-
- public void encode(
- BCPGOutputStream out)
- throws IOException
- {
- out.writePacket(USER_ID, idData, true);
- }
-}
+package org.bouncycastle.bcpg;
+
+import java.io.IOException;
+
+import org.bouncycastle.util.Strings;
+
+/**
+ * Basic type for a user ID packet.
+ */
+public class UserIDPacket
+ extends ContainedPacket
+{
+ private byte[] idData;
+
+ public UserIDPacket(
+ BCPGInputStream in)
+ throws IOException
+ {
+ this.idData = in.readAll();
+ }
+
+ public UserIDPacket(
+ String id)
+ {
+ this.idData = Strings.toUTF8ByteArray(id);
+ }
+
+ public String getID()
+ {
+ return Strings.fromUTF8ByteArray(idData);
+ }
+
+ public void encode(
+ BCPGOutputStream out)
+ throws IOException
+ {
+ out.writePacket(USER_ID, idData, true);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java b/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
index 356f8b6e..947bc5c4 100644
--- a/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
+++ b/src/main/java/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
@@ -1,131 +1,131 @@
-package org.bouncycastle.crypto.agreement.kdf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.util.Pack;
-
-/**
- * RFC 2631 Diffie-hellman KEK derivation function.
- */
-public class DHKEKGenerator
- implements DerivationFunction
-{
- private final Digest digest;
-
- private DERObjectIdentifier algorithm;
- private int keySize;
- private byte[] z;
- private byte[] partyAInfo;
-
- public DHKEKGenerator(
- Digest digest)
- {
- this.digest = digest;
- }
-
- public void init(DerivationParameters param)
- {
- DHKDFParameters params = (DHKDFParameters)param;
-
- this.algorithm = params.getAlgorithm();
- this.keySize = params.getKeySize();
- this.z = params.getZ();
- this.partyAInfo = params.getExtraInfo();
- }
-
- public Digest getDigest()
- {
- return digest;
- }
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException
- {
- if ((out.length - len) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
-
- long oBytes = len;
- int outLen = digest.getDigestSize();
-
- //
- // this is at odds with the standard implementation, the
- // maximum value should be hBits * (2^32 - 1) where hBits
- // is the digest output size in bits. We can't have an
- // array with a long index at the moment...
- //
- if (oBytes > ((2L << 32) - 1))
- {
- throw new IllegalArgumentException("Output length too large");
- }
-
- int cThreshold = (int)((oBytes + outLen - 1) / outLen);
-
- byte[] dig = new byte[digest.getDigestSize()];
-
- int counter = 1;
-
- for (int i = 0; i < cThreshold; i++)
- {
- digest.update(z, 0, z.length);
-
- // OtherInfo
- ASN1EncodableVector v1 = new ASN1EncodableVector();
- // KeySpecificInfo
- ASN1EncodableVector v2 = new ASN1EncodableVector();
-
- v2.add(algorithm);
- v2.add(new DEROctetString(Pack.intToBigEndian(counter)));
-
- v1.add(new DERSequence(v2));
-
- if (partyAInfo != null)
- {
- v1.add(new DERTaggedObject(true, 0, new DEROctetString(partyAInfo)));
- }
-
- v1.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
-
- try
- {
- byte[] other = new DERSequence(v1).getEncoded(ASN1Encoding.DER);
-
- digest.update(other, 0, other.length);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to encode parameter info: " + e.getMessage());
- }
-
- digest.doFinal(dig, 0);
-
- if (len > outLen)
- {
- System.arraycopy(dig, 0, out, outOff, outLen);
- outOff += outLen;
- len -= outLen;
- }
- else
- {
- System.arraycopy(dig, 0, out, outOff, len);
- }
-
- counter++;
- }
-
- digest.reset();
-
- return (int)oBytes;
- }
-}
+package org.bouncycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationFunction;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * RFC 2631 Diffie-hellman KEK derivation function.
+ */
+public class DHKEKGenerator
+ implements DerivationFunction
+{
+ private final Digest digest;
+
+ private DERObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+ private byte[] partyAInfo;
+
+ public DHKEKGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ this.partyAInfo = params.getExtraInfo();
+ }
+
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ int counter = 1;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(z, 0, z.length);
+
+ // OtherInfo
+ ASN1EncodableVector v1 = new ASN1EncodableVector();
+ // KeySpecificInfo
+ ASN1EncodableVector v2 = new ASN1EncodableVector();
+
+ v2.add(algorithm);
+ v2.add(new DEROctetString(Pack.intToBigEndian(counter)));
+
+ v1.add(new DERSequence(v2));
+
+ if (partyAInfo != null)
+ {
+ v1.add(new DERTaggedObject(true, 0, new DEROctetString(partyAInfo)));
+ }
+
+ v1.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
+
+ try
+ {
+ byte[] other = new DERSequence(v1).getEncoded(ASN1Encoding.DER);
+
+ digest.update(other, 0, other.length);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to encode parameter info: " + e.getMessage());
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ counter++;
+ }
+
+ digest.reset();
+
+ return (int)oBytes;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java b/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
index 03ca321f..68039533 100644
--- a/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
+++ b/src/main/java/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
@@ -1,74 +1,74 @@
-package org.bouncycastle.crypto.agreement.kdf;
-
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Encoding;
-import org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.util.Pack;
-
-/**
- * X9.63 based key derivation function for ECDH CMS.
- */
-public class ECDHKEKGenerator
- implements DerivationFunction
-{
- private DerivationFunction kdf;
-
- private ASN1ObjectIdentifier algorithm;
- private int keySize;
- private byte[] z;
-
- public ECDHKEKGenerator(
- Digest digest)
- {
- this.kdf = new KDF2BytesGenerator(digest);
- }
-
- public void init(DerivationParameters param)
- {
- DHKDFParameters params = (DHKDFParameters)param;
-
- this.algorithm = params.getAlgorithm();
- this.keySize = params.getKeySize();
- this.z = params.getZ();
- }
-
- public Digest getDigest()
- {
- return kdf.getDigest();
- }
-
- public int generateBytes(byte[] out, int outOff, int len)
- throws DataLengthException, IllegalArgumentException
- {
- // TODO Create an ASN.1 class for this (RFC3278)
- // ECC-CMS-SharedInfo
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- v.add(new AlgorithmIdentifier(algorithm, DERNull.INSTANCE));
- v.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
-
- try
- {
- kdf.init(new KDFParameters(z, new DERSequence(v).getEncoded(ASN1Encoding.DER)));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("unable to initialise kdf: " + e.getMessage());
- }
-
- return kdf.generateBytes(out, outOff, len);
- }
-}
+package org.bouncycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationFunction;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
+import org.bouncycastle.crypto.params.KDFParameters;
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * X9.63 based key derivation function for ECDH CMS.
+ */
+public class ECDHKEKGenerator
+ implements DerivationFunction
+{
+ private DerivationFunction kdf;
+
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+
+ public ECDHKEKGenerator(
+ Digest digest)
+ {
+ this.kdf = new KDF2BytesGenerator(digest);
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ }
+
+ public Digest getDigest()
+ {
+ return kdf.getDigest();
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ // TODO Create an ASN.1 class for this (RFC3278)
+ // ECC-CMS-SharedInfo
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new AlgorithmIdentifier(algorithm, DERNull.INSTANCE));
+ v.add(new DERTaggedObject(true, 2, new DEROctetString(Pack.intToBigEndian(keySize))));
+
+ try
+ {
+ kdf.init(new KDFParameters(z, new DERSequence(v).getEncoded(ASN1Encoding.DER)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to initialise kdf: " + e.getMessage());
+ }
+
+ return kdf.generateBytes(out, outOff, len);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java b/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java
index f77d5f56..ea8556de 100755
--- a/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java
+++ b/src/main/java/org/bouncycastle/crypto/engines/IESEngine.java
@@ -1,398 +1,398 @@
-package org.bouncycastle.crypto.engines;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.EphemeralKeyPair;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.KeyParser;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.IESParameters;
-import org.bouncycastle.crypto.params.IESWithCipherParameters;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.util.Pack;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-
-/**
- * Support class for constructing integrated encryption ciphers
- * for doing basic message exchanges on top of key agreement ciphers.
- * Follows the description given in IEEE Std 1363a.
- */
-public class IESEngine
-{
- BasicAgreement agree;
- DerivationFunction kdf;
- Mac mac;
- BufferedBlockCipher cipher;
- byte[] macBuf;
-
- boolean forEncryption;
- CipherParameters privParam, pubParam;
- IESParameters param;
-
- byte[] V;
- private EphemeralKeyPairGenerator keyPairGenerator;
- private KeyParser keyParser;
-
-
- /**
- * set up for use with stream mode, where the key derivation function
- * is used to provide a stream of bytes to xor with the message.
- *
- * @param agree the key agreement used as the basis for the encryption
- * @param kdf the key derivation function used for byte generation
- * @param mac the message authentication code generator for the message
- */
- public IESEngine(
- BasicAgreement agree,
- DerivationFunction kdf,
- Mac mac)
- {
- this.agree = agree;
- this.kdf = kdf;
- this.mac = mac;
- this.macBuf = new byte[mac.getMacSize()];
- this.cipher = null;
- }
-
-
- /**
- * set up for use in conjunction with a block cipher to handle the
- * message.
- *
- * @param agree the key agreement used as the basis for the encryption
- * @param kdf the key derivation function used for byte generation
- * @param mac the message authentication code generator for the message
- * @param cipher the cipher to used for encrypting the message
- */
- public IESEngine(
- BasicAgreement agree,
- DerivationFunction kdf,
- Mac mac,
- BufferedBlockCipher cipher)
- {
- this.agree = agree;
- this.kdf = kdf;
- this.mac = mac;
- this.macBuf = new byte[mac.getMacSize()];
- this.cipher = cipher;
- }
-
-
- /**
- * Initialise the encryptor.
- *
- * @param forEncryption whether or not this is encryption/decryption.
- * @param privParam our private key parameters
- * @param pubParam the recipient's/sender's public key parameters
- * @param param encoding and derivation parameters.
- */
- public void init(
- boolean forEncryption,
- CipherParameters privParam,
- CipherParameters pubParam,
- CipherParameters param)
- {
- this.forEncryption = forEncryption;
- this.privParam = privParam;
- this.pubParam = pubParam;
- this.param = (IESParameters)param;
- this.V = new byte[0];
- }
-
-
- /**
- * Initialise the encryptor.
- *
- * @param publicKey the recipient's/sender's public key parameters
- * @param params encoding and derivation parameters.
- * @param ephemeralKeyPairGenerator the ephemeral key pair generator to use.
- */
- public void init(AsymmetricKeyParameter publicKey, CipherParameters params, EphemeralKeyPairGenerator ephemeralKeyPairGenerator)
- {
- this.forEncryption = true;
- this.pubParam = publicKey;
- this.param = (IESParameters)params;
- this.keyPairGenerator = ephemeralKeyPairGenerator;
- }
-
- /**
- * Initialise the encryptor.
- *
- * @param privateKey the recipient's private key.
- * @param params encoding and derivation parameters.
- * @param publicKeyParser the parser for reading the ephemeral public key.
- */
- public void init(AsymmetricKeyParameter privateKey, CipherParameters params, KeyParser publicKeyParser)
- {
- this.forEncryption = false;
- this.privParam = privateKey;
- this.param = (IESParameters)params;
- this.keyParser = publicKeyParser;
- }
-
- public BufferedBlockCipher getCipher()
- {
- return cipher;
- }
-
- public Mac getMac()
- {
- return mac;
- }
-
- private byte[] encryptBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] C = null, K = null, K1 = null, K2 = null;
- int len;
-
- if (cipher == null)
- {
- // Streaming mode.
- K1 = new byte[inLen];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
-
- if (V.length != 0)
- {
- System.arraycopy(K, 0, K2, 0, K2.length);
- System.arraycopy(K, K2.length, K1, 0, K1.length);
- }
- else
- {
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, inLen, K2, 0, K2.length);
- }
-
- C = new byte[inLen];
-
- for (int i = 0; i != inLen; i++)
- {
- C[i] = (byte)(in[inOff + i] ^ K1[i]);
- }
- len = inLen;
- }
- else
- {
- // Block cipher mode.
- K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
-
- cipher.init(true, new KeyParameter(K1));
- C = new byte[cipher.getOutputSize(inLen)];
- len = cipher.processBytes(in, inOff, inLen, C, 0);
- len += cipher.doFinal(C, len);
- }
-
-
- // Convert the length of the encoding vector into a byte array.
- byte[] P2 = param.getEncodingV();
- byte[] L2 = new byte[4];
- if (V.length != 0 && P2 != null)
- {
- Pack.intToBigEndian(P2.length * 8, L2, 0);
- }
-
-
- // Apply the MAC.
- byte[] T = new byte[mac.getMacSize()];
-
- mac.init(new KeyParameter(K2));
- mac.update(C, 0, C.length);
- if (P2 != null)
- {
- mac.update(P2, 0, P2.length);
- }
- if (V.length != 0)
- {
- mac.update(L2, 0, L2.length);
- }
- mac.doFinal(T, 0);
-
-
- // Output the triple (V,C,T).
- byte[] Output = new byte[V.length + len + T.length];
- System.arraycopy(V, 0, Output, 0, V.length);
- System.arraycopy(C, 0, Output, V.length, len);
- System.arraycopy(T, 0, Output, V.length + len, T.length);
- return Output;
- }
-
- private byte[] decryptBlock(
- byte[] in_enc,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- byte[] M = null, K = null, K1 = null, K2 = null;
- int len;
-
- if (cipher == null)
- {
- // Streaming mode.
- K1 = new byte[inLen - V.length - mac.getMacSize()];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
-
- if (V.length != 0)
- {
- System.arraycopy(K, 0, K2, 0, K2.length);
- System.arraycopy(K, K2.length, K1, 0, K1.length);
- }
- else
- {
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
- }
-
- M = new byte[K1.length];
-
- for (int i = 0; i != K1.length; i++)
- {
- M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
- }
-
- len = K1.length;
- }
- else
- {
- // Block cipher mode.
- K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
- K2 = new byte[param.getMacKeySize() / 8];
- K = new byte[K1.length + K2.length];
-
- kdf.generateBytes(K, 0, K.length);
- System.arraycopy(K, 0, K1, 0, K1.length);
- System.arraycopy(K, K1.length, K2, 0, K2.length);
-
- cipher.init(false, new KeyParameter(K1));
-
- M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
- len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
- len += cipher.doFinal(M, len);
- }
-
-
- // Convert the length of the encoding vector into a byte array.
- byte[] P2 = param.getEncodingV();
- byte[] L2 = new byte[4];
- if (V.length != 0 && P2 != null)
- {
- Pack.intToBigEndian(P2.length * 8, L2, 0);
- }
-
-
- // Verify the MAC.
- int end = inOff + inLen;
- byte[] T1 = Arrays.copyOfRange(in_enc, end - mac.getMacSize(), end);
-
- byte[] T2 = new byte[T1.length];
- mac.init(new KeyParameter(K2));
- mac.update(in_enc, inOff + V.length, inLen - V.length - T2.length);
-
- if (P2 != null)
- {
- mac.update(P2, 0, P2.length);
- }
- if (V.length != 0)
- {
- mac.update(L2, 0, L2.length);
- }
- mac.doFinal(T2, 0);
-
- if (!Arrays.constantTimeAreEqual(T1, T2))
- {
- throw new InvalidCipherTextException("Invalid MAC.");
- }
-
-
- // Output the message.
- return Arrays.copyOfRange(M, 0, len);
- }
-
-
- public byte[] processBlock(
- byte[] in,
- int inOff,
- int inLen)
- throws InvalidCipherTextException
- {
- if (forEncryption)
- {
- if (keyPairGenerator != null)
- {
- EphemeralKeyPair ephKeyPair = keyPairGenerator.generate();
-
- this.privParam = ephKeyPair.getKeyPair().getPrivate();
- this.V = ephKeyPair.getEncodedPublicKey();
- }
- }
- else
- {
- if (keyParser != null)
- {
- ByteArrayInputStream bIn = new ByteArrayInputStream(in, inOff, inLen);
-
- try
- {
- this.pubParam = keyParser.readKey(bIn);
- }
- catch (IOException e)
- {
- throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.getMessage(), e);
- }
-
- int encLength = (inLen - bIn.available());
- this.V = Arrays.copyOfRange(in, inOff, inOff + encLength);
- }
- }
-
- // Compute the common value and convert to byte array.
- agree.init(privParam);
- BigInteger z = agree.calculateAgreement(pubParam);
- byte[] Z = BigIntegers.asUnsignedByteArray(agree.getFieldSize(), z);
-
- // Create input to KDF.
- byte[] VZ;
- if (V.length != 0)
- {
- VZ = new byte[V.length + Z.length];
- System.arraycopy(V, 0, VZ, 0, V.length);
- System.arraycopy(Z, 0, VZ, V.length, Z.length);
- }
- else
- {
- VZ = Z;
- }
-
- // Initialise the KDF.
- KDFParameters kdfParam = new KDFParameters(VZ, param.getDerivationV());
- kdf.init(kdfParam);
-
- return forEncryption
- ? encryptBlock(in, inOff, inLen)
- : decryptBlock(in, inOff, inLen);
- }
-}
+package org.bouncycastle.crypto.engines;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.BasicAgreement;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DerivationFunction;
+import org.bouncycastle.crypto.EphemeralKeyPair;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.KeyParser;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
+import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import org.bouncycastle.crypto.params.IESParameters;
+import org.bouncycastle.crypto.params.IESWithCipherParameters;
+import org.bouncycastle.crypto.params.KDFParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.util.Pack;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.BigIntegers;
+
+/**
+ * Support class for constructing integrated encryption ciphers
+ * for doing basic message exchanges on top of key agreement ciphers.
+ * Follows the description given in IEEE Std 1363a.
+ */
+public class IESEngine
+{
+ BasicAgreement agree;
+ DerivationFunction kdf;
+ Mac mac;
+ BufferedBlockCipher cipher;
+ byte[] macBuf;
+
+ boolean forEncryption;
+ CipherParameters privParam, pubParam;
+ IESParameters param;
+
+ byte[] V;
+ private EphemeralKeyPairGenerator keyPairGenerator;
+ private KeyParser keyParser;
+
+
+ /**
+ * set up for use with stream mode, where the key derivation function
+ * is used to provide a stream of bytes to xor with the message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = null;
+ }
+
+
+ /**
+ * set up for use in conjunction with a block cipher to handle the
+ * message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ * @param cipher the cipher to used for encrypting the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac,
+ BufferedBlockCipher cipher)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = cipher;
+ }
+
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param forEncryption whether or not this is encryption/decryption.
+ * @param privParam our private key parameters
+ * @param pubParam the recipient's/sender's public key parameters
+ * @param param encoding and derivation parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters privParam,
+ CipherParameters pubParam,
+ CipherParameters param)
+ {
+ this.forEncryption = forEncryption;
+ this.privParam = privParam;
+ this.pubParam = pubParam;
+ this.param = (IESParameters)param;
+ this.V = new byte[0];
+ }
+
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param publicKey the recipient's/sender's public key parameters
+ * @param params encoding and derivation parameters.
+ * @param ephemeralKeyPairGenerator the ephemeral key pair generator to use.
+ */
+ public void init(AsymmetricKeyParameter publicKey, CipherParameters params, EphemeralKeyPairGenerator ephemeralKeyPairGenerator)
+ {
+ this.forEncryption = true;
+ this.pubParam = publicKey;
+ this.param = (IESParameters)params;
+ this.keyPairGenerator = ephemeralKeyPairGenerator;
+ }
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param privateKey the recipient's private key.
+ * @param params encoding and derivation parameters.
+ * @param publicKeyParser the parser for reading the ephemeral public key.
+ */
+ public void init(AsymmetricKeyParameter privateKey, CipherParameters params, KeyParser publicKeyParser)
+ {
+ this.forEncryption = false;
+ this.privParam = privateKey;
+ this.param = (IESParameters)params;
+ this.keyParser = publicKeyParser;
+ }
+
+ public BufferedBlockCipher getCipher()
+ {
+ return cipher;
+ }
+
+ public Mac getMac()
+ {
+ return mac;
+ }
+
+ private byte[] encryptBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] C = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, inLen, K2, 0, K2.length);
+ }
+
+ C = new byte[inLen];
+
+ for (int i = 0; i != inLen; i++)
+ {
+ C[i] = (byte)(in[inOff + i] ^ K1[i]);
+ }
+ len = inLen;
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ cipher.init(true, new KeyParameter(K1));
+ C = new byte[cipher.getOutputSize(inLen)];
+ len = cipher.processBytes(in, inOff, inLen, C, 0);
+ len += cipher.doFinal(C, len);
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0 && P2 != null)
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+
+
+ // Apply the MAC.
+ byte[] T = new byte[mac.getMacSize()];
+
+ mac.init(new KeyParameter(K2));
+ mac.update(C, 0, C.length);
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T, 0);
+
+
+ // Output the triple (V,C,T).
+ byte[] Output = new byte[V.length + len + T.length];
+ System.arraycopy(V, 0, Output, 0, V.length);
+ System.arraycopy(C, 0, Output, V.length, len);
+ System.arraycopy(T, 0, Output, V.length + len, T.length);
+ return Output;
+ }
+
+ private byte[] decryptBlock(
+ byte[] in_enc,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] M = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen - V.length - mac.getMacSize()];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+ }
+
+ M = new byte[K1.length];
+
+ for (int i = 0; i != K1.length; i++)
+ {
+ M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
+ }
+
+ len = K1.length;
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ cipher.init(false, new KeyParameter(K1));
+
+ M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
+ len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
+ len += cipher.doFinal(M, len);
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0 && P2 != null)
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+
+
+ // Verify the MAC.
+ int end = inOff + inLen;
+ byte[] T1 = Arrays.copyOfRange(in_enc, end - mac.getMacSize(), end);
+
+ byte[] T2 = new byte[T1.length];
+ mac.init(new KeyParameter(K2));
+ mac.update(in_enc, inOff + V.length, inLen - V.length - T2.length);
+
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T2, 0);
+
+ if (!Arrays.constantTimeAreEqual(T1, T2))
+ {
+ throw new InvalidCipherTextException("Invalid MAC.");
+ }
+
+
+ // Output the message.
+ return Arrays.copyOfRange(M, 0, len);
+ }
+
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ if (keyPairGenerator != null)
+ {
+ EphemeralKeyPair ephKeyPair = keyPairGenerator.generate();
+
+ this.privParam = ephKeyPair.getKeyPair().getPrivate();
+ this.V = ephKeyPair.getEncodedPublicKey();
+ }
+ }
+ else
+ {
+ if (keyParser != null)
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(in, inOff, inLen);
+
+ try
+ {
+ this.pubParam = keyParser.readKey(bIn);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.getMessage(), e);
+ }
+
+ int encLength = (inLen - bIn.available());
+ this.V = Arrays.copyOfRange(in, inOff, inOff + encLength);
+ }
+ }
+
+ // Compute the common value and convert to byte array.
+ agree.init(privParam);
+ BigInteger z = agree.calculateAgreement(pubParam);
+ byte[] Z = BigIntegers.asUnsignedByteArray(agree.getFieldSize(), z);
+
+ // Create input to KDF.
+ byte[] VZ;
+ if (V.length != 0)
+ {
+ VZ = new byte[V.length + Z.length];
+ System.arraycopy(V, 0, VZ, 0, V.length);
+ System.arraycopy(Z, 0, VZ, V.length, Z.length);
+ }
+ else
+ {
+ VZ = Z;
+ }
+
+ // Initialise the KDF.
+ KDFParameters kdfParam = new KDFParameters(VZ, param.getDerivationV());
+ kdf.init(kdfParam);
+
+ return forEncryption
+ ? encryptBlock(in, inOff, inLen)
+ : decryptBlock(in, inOff, inLen);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java b/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
index c6e39986..2ef8dd2b 100644
--- a/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
+++ b/src/main/java/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
@@ -1,142 +1,142 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.ISO18033KDFParameters;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.util.Pack;
-
-/**
- * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO
- * 18033 <br>
- * This implementation is based on ISO 18033/P1363a.
- */
-public class BaseKDFBytesGenerator implements DerivationFunction
-{
- private int counterStart;
- private Digest digest;
- private byte[] shared;
- private byte[] iv;
-
- /**
- * Construct a KDF Parameters generator.
- * <p>
- *
- * @param counterStart
- * value of counter.
- * @param digest
- * the digest to be used as the source of derived keys.
- */
- protected BaseKDFBytesGenerator(int counterStart, Digest digest)
- {
- this.counterStart = counterStart;
- this.digest = digest;
- }
-
- public void init(DerivationParameters param)
- {
- if (param instanceof KDFParameters)
- {
- KDFParameters p = (KDFParameters)param;
-
- shared = p.getSharedSecret();
- iv = p.getIV();
- }
- else if (param instanceof ISO18033KDFParameters)
- {
- ISO18033KDFParameters p = (ISO18033KDFParameters)param;
-
- shared = p.getSeed();
- iv = null;
- }
- else
- {
- throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
- }
- }
-
- /**
- * return the underlying digest.
- */
- public Digest getDigest()
- {
- return digest;
- }
-
- /**
- * fill len bytes of the output buffer with bytes generated from the
- * derivation function.
- *
- * @throws IllegalArgumentException
- * if the size of the request will cause an overflow.
- * @throws DataLengthException
- * if the out buffer is too small.
- */
- public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
- IllegalArgumentException
- {
- if ((out.length - len) < outOff)
- {
- throw new DataLengthException("output buffer too small");
- }
-
- long oBytes = len;
- int outLen = digest.getDigestSize();
-
- //
- // this is at odds with the standard implementation, the
- // maximum value should be hBits * (2^32 - 1) where hBits
- // is the digest output size in bits. We can't have an
- // array with a long index at the moment...
- //
- if (oBytes > ((2L << 32) - 1))
- {
- throw new IllegalArgumentException("Output length too large");
- }
-
- int cThreshold = (int)((oBytes + outLen - 1) / outLen);
-
- byte[] dig = new byte[digest.getDigestSize()];
-
- byte[] C = new byte[4];
- Pack.intToBigEndian(counterStart, C, 0);
-
- int counterBase = counterStart & ~0xFF;
-
- for (int i = 0; i < cThreshold; i++)
- {
- digest.update(shared, 0, shared.length);
- digest.update(C, 0, C.length);
-
- if (iv != null)
- {
- digest.update(iv, 0, iv.length);
- }
-
- digest.doFinal(dig, 0);
-
- if (len > outLen)
- {
- System.arraycopy(dig, 0, out, outOff, outLen);
- outOff += outLen;
- len -= outLen;
- }
- else
- {
- System.arraycopy(dig, 0, out, outOff, len);
- }
-
- if (++C[3] == 0)
- {
- counterBase += 0x100;
- Pack.intToBigEndian(counterBase, C, 0);
- }
- }
-
- digest.reset();
-
- return (int)oBytes;
- }
-}
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.DerivationFunction;
+import org.bouncycastle.crypto.DerivationParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.params.ISO18033KDFParameters;
+import org.bouncycastle.crypto.params.KDFParameters;
+import org.bouncycastle.crypto.util.Pack;
+
+/**
+ * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO
+ * 18033 <br>
+ * This implementation is based on ISO 18033/P1363a.
+ */
+public class BaseKDFBytesGenerator implements DerivationFunction
+{
+ private int counterStart;
+ private Digest digest;
+ private byte[] shared;
+ private byte[] iv;
+
+ /**
+ * Construct a KDF Parameters generator.
+ * <p>
+ *
+ * @param counterStart
+ * value of counter.
+ * @param digest
+ * the digest to be used as the source of derived keys.
+ */
+ protected BaseKDFBytesGenerator(int counterStart, Digest digest)
+ {
+ this.counterStart = counterStart;
+ this.digest = digest;
+ }
+
+ public void init(DerivationParameters param)
+ {
+ if (param instanceof KDFParameters)
+ {
+ KDFParameters p = (KDFParameters)param;
+
+ shared = p.getSharedSecret();
+ iv = p.getIV();
+ }
+ else if (param instanceof ISO18033KDFParameters)
+ {
+ ISO18033KDFParameters p = (ISO18033KDFParameters)param;
+
+ shared = p.getSeed();
+ iv = null;
+ }
+ else
+ {
+ throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
+ }
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from the
+ * derivation function.
+ *
+ * @throws IllegalArgumentException
+ * if the size of the request will cause an overflow.
+ * @throws DataLengthException
+ * if the out buffer is too small.
+ */
+ public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException,
+ IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ byte[] C = new byte[4];
+ Pack.intToBigEndian(counterStart, C, 0);
+
+ int counterBase = counterStart & ~0xFF;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(shared, 0, shared.length);
+ digest.update(C, 0, C.length);
+
+ if (iv != null)
+ {
+ digest.update(iv, 0, iv.length);
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ if (++C[3] == 0)
+ {
+ counterBase += 0x100;
+ Pack.intToBigEndian(counterBase, C, 0);
+ }
+ }
+
+ digest.reset();
+
+ return (int)oBytes;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index 600dd297..9a6e2e0c 100644
--- a/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -1,378 +1,378 @@
-package org.bouncycastle.crypto.modes;
-
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
-import org.bouncycastle.crypto.params.AEADParameters;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.util.Arrays;
-
-/**
- * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
- * NIST Special Publication 800-38C.
- * <p>
- * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
- */
-public class CCMBlockCipher
- implements AEADBlockCipher
-{
- private BlockCipher cipher;
- private int blockSize;
- private boolean forEncryption;
- private byte[] nonce;
- private byte[] initialAssociatedText;
- private int macSize;
- private CipherParameters keyParam;
- private byte[] macBlock;
- private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
- private ByteArrayOutputStream data = new ByteArrayOutputStream();
-
- /**
- * Basic constructor.
- *
- * @param c the block cipher to be used.
- */
- public CCMBlockCipher(BlockCipher c)
- {
- this.cipher = c;
- this.blockSize = c.getBlockSize();
- this.macBlock = new byte[blockSize];
-
- if (blockSize != 16)
- {
- throw new IllegalArgumentException("cipher required with a block size of 16.");
- }
- }
-
- /**
- * return the underlying block cipher that we are wrapping.
- *
- * @return the underlying block cipher that we are wrapping.
- */
- public BlockCipher getUnderlyingCipher()
- {
- return cipher;
- }
-
-
- public void init(boolean forEncryption, CipherParameters params)
- throws IllegalArgumentException
- {
- this.forEncryption = forEncryption;
-
- if (params instanceof AEADParameters)
- {
- AEADParameters param = (AEADParameters)params;
-
- nonce = param.getNonce();
- initialAssociatedText = param.getAssociatedText();
- macSize = param.getMacSize() / 8;
- keyParam = param.getKey();
- }
- else if (params instanceof ParametersWithIV)
- {
- ParametersWithIV param = (ParametersWithIV)params;
-
- nonce = param.getIV();
- initialAssociatedText = null;
- macSize = macBlock.length / 2;
- keyParam = param.getParameters();
- }
- else
- {
- throw new IllegalArgumentException("invalid parameters passed to CCM");
- }
-
- if (nonce == null || nonce.length < 7 || nonce.length > 13)
- {
- throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
- }
- }
-
- public String getAlgorithmName()
- {
- 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
- {
- data.write(in);
-
- return 0;
- }
-
- public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
- throws DataLengthException, IllegalStateException
- {
- data.write(in, inOff, inLen);
-
- return 0;
- }
-
- public int doFinal(byte[] out, int outOff)
- throws IllegalStateException, InvalidCipherTextException
- {
- byte[] text = data.toByteArray();
- byte[] enc = processPacket(text, 0, text.length);
-
- System.arraycopy(enc, 0, out, outOff, enc.length);
-
- reset();
-
- return enc.length;
- }
-
- public void reset()
- {
- cipher.reset();
- associatedText.reset();
- data.reset();
- }
-
- /**
- * Returns a byte array containing the mac calculated as part of the
- * last encrypt or decrypt operation.
- *
- * @return the last mac calculated.
- */
- public byte[] getMac()
- {
- byte[] mac = new byte[macSize];
-
- System.arraycopy(macBlock, 0, mac, 0, mac.length);
-
- return mac;
- }
-
- public int getUpdateOutputSize(int len)
- {
- return 0;
- }
-
- public int getOutputSize(int len)
- {
- int totalData = len + data.size();
-
- if (forEncryption)
- {
- 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.");
- }
-
- int n = nonce.length;
- int q = 15 - n;
- if (q < 4)
- {
- int limitLen = 1 << (8 * q);
- if (inLen >= limitLen)
- {
- throw new IllegalStateException("CCM packet too large for choice of q.");
- }
- }
-
- byte[] iv = new byte[blockSize];
- iv[0] = (byte)((q - 1) & 0x7);
- System.arraycopy(nonce, 0, iv, 1, nonce.length);
-
- BlockCipher ctrCipher = new SICBlockCipher(cipher);
- ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
-
- int index = inOff;
- int outOff = 0;
- byte[] output;
-
- if (forEncryption)
- {
- output = 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, output, 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, output, outOff, inLen - index);
-
- outOff += inLen - index;
-
- System.arraycopy(macBlock, 0, output, outOff, output.length - outOff);
- }
- else
- {
- output = 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 < output.length - blockSize)
- {
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
- }
-
- byte[] block = new byte[blockSize];
-
- System.arraycopy(in, index, block, 0, output.length - outOff);
-
- ctrCipher.processBlock(block, 0, block, 0);
-
- System.arraycopy(block, 0, output, outOff, output.length - outOff);
-
- byte[] calculatedMacBlock = new byte[blockSize];
-
- calculateMac(output, 0, output.length, calculatedMacBlock);
-
- if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
- {
- throw new InvalidCipherTextException("mac check in CCM failed");
- }
- }
-
- return output;
- }
-
- private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
- {
- Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
-
- cMac.init(keyParam);
-
- //
- // build b0
- //
- byte[] b0 = new byte[16];
-
- if (hasAssociatedText())
- {
- b0[0] |= 0x40;
- }
-
- b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
-
- b0[0] |= ((15 - nonce.length) - 1) & 0x7;
-
- System.arraycopy(nonce, 0, b0, 1, nonce.length);
-
- int q = dataLen;
- int count = 1;
- while (q > 0)
- {
- b0[b0.length - count] = (byte)(q & 0xff);
- q >>>= 8;
- count++;
- }
-
- cMac.update(b0, 0, b0.length);
-
- //
- // process associated text
- //
- if (hasAssociatedText())
- {
- int extra;
-
- int textLength = getAssociatedTextLength();
- if (textLength < ((1 << 16) - (1 << 8)))
- {
- cMac.update((byte)(textLength >> 8));
- cMac.update((byte)textLength);
-
- extra = 2;
- }
- else // can't go any higher than 2^32
- {
- cMac.update((byte)0xff);
- cMac.update((byte)0xfe);
- cMac.update((byte)(textLength >> 24));
- cMac.update((byte)(textLength >> 16));
- cMac.update((byte)(textLength >> 8));
- cMac.update((byte)textLength);
-
- extra = 6;
- }
-
- 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 = extra; i != 16; i++)
- {
- cMac.update((byte)0x00);
- }
- }
- }
-
- //
- // add the text
- //
- cMac.update(data, dataOff, dataLen);
-
- return cMac.doFinal(macBlock, 0);
- }
-
- private int getAssociatedTextLength()
- {
- return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
- }
-
- private boolean hasAssociatedText()
- {
- return getAssociatedTextLength() > 0;
- }
-}
+package org.bouncycastle.crypto.modes;
+
+import java.io.ByteArrayOutputStream;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
+import org.bouncycastle.crypto.params.AEADParameters;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+ * NIST Special Publication 800-38C.
+ * <p>
+ * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
+ */
+public class CCMBlockCipher
+ implements AEADBlockCipher
+{
+ private BlockCipher cipher;
+ private int blockSize;
+ private boolean forEncryption;
+ private byte[] nonce;
+ private byte[] initialAssociatedText;
+ private int macSize;
+ private CipherParameters keyParam;
+ private byte[] macBlock;
+ private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
+ private ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ /**
+ * Basic constructor.
+ *
+ * @param c the block cipher to be used.
+ */
+ public CCMBlockCipher(BlockCipher c)
+ {
+ this.cipher = c;
+ this.blockSize = c.getBlockSize();
+ this.macBlock = new byte[blockSize];
+
+ if (blockSize != 16)
+ {
+ throw new IllegalArgumentException("cipher required with a block size of 16.");
+ }
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+ macSize = param.getMacSize() / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = macBlock.length / 2;
+ keyParam = param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to CCM");
+ }
+
+ if (nonce == null || nonce.length < 7 || nonce.length > 13)
+ {
+ throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ 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
+ {
+ data.write(in);
+
+ return 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ data.write(in, inOff, inLen);
+
+ return 0;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ byte[] text = data.toByteArray();
+ byte[] enc = processPacket(text, 0, text.length);
+
+ System.arraycopy(enc, 0, out, outOff, enc.length);
+
+ reset();
+
+ return enc.length;
+ }
+
+ public void reset()
+ {
+ cipher.reset();
+ associatedText.reset();
+ data.reset();
+ }
+
+ /**
+ * Returns a byte array containing the mac calculated as part of the
+ * last encrypt or decrypt operation.
+ *
+ * @return the last mac calculated.
+ */
+ public byte[] getMac()
+ {
+ byte[] mac = new byte[macSize];
+
+ System.arraycopy(macBlock, 0, mac, 0, mac.length);
+
+ return mac;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ return 0;
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + data.size();
+
+ if (forEncryption)
+ {
+ 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.");
+ }
+
+ int n = nonce.length;
+ int q = 15 - n;
+ if (q < 4)
+ {
+ int limitLen = 1 << (8 * q);
+ if (inLen >= limitLen)
+ {
+ throw new IllegalStateException("CCM packet too large for choice of q.");
+ }
+ }
+
+ byte[] iv = new byte[blockSize];
+ iv[0] = (byte)((q - 1) & 0x7);
+ System.arraycopy(nonce, 0, iv, 1, nonce.length);
+
+ BlockCipher ctrCipher = new SICBlockCipher(cipher);
+ ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
+
+ int index = inOff;
+ int outOff = 0;
+ byte[] output;
+
+ if (forEncryption)
+ {
+ output = 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, output, 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, output, outOff, inLen - index);
+
+ outOff += inLen - index;
+
+ System.arraycopy(macBlock, 0, output, outOff, output.length - outOff);
+ }
+ else
+ {
+ output = 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 < output.length - blockSize)
+ {
+ ctrCipher.processBlock(in, index, output, outOff);
+ outOff += blockSize;
+ index += blockSize;
+ }
+
+ byte[] block = new byte[blockSize];
+
+ System.arraycopy(in, index, block, 0, output.length - outOff);
+
+ ctrCipher.processBlock(block, 0, block, 0);
+
+ System.arraycopy(block, 0, output, outOff, output.length - outOff);
+
+ byte[] calculatedMacBlock = new byte[blockSize];
+
+ calculateMac(output, 0, output.length, calculatedMacBlock);
+
+ if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
+ {
+ throw new InvalidCipherTextException("mac check in CCM failed");
+ }
+ }
+
+ return output;
+ }
+
+ private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+ {
+ Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
+
+ cMac.init(keyParam);
+
+ //
+ // build b0
+ //
+ byte[] b0 = new byte[16];
+
+ if (hasAssociatedText())
+ {
+ b0[0] |= 0x40;
+ }
+
+ b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
+
+ b0[0] |= ((15 - nonce.length) - 1) & 0x7;
+
+ System.arraycopy(nonce, 0, b0, 1, nonce.length);
+
+ int q = dataLen;
+ int count = 1;
+ while (q > 0)
+ {
+ b0[b0.length - count] = (byte)(q & 0xff);
+ q >>>= 8;
+ count++;
+ }
+
+ cMac.update(b0, 0, b0.length);
+
+ //
+ // process associated text
+ //
+ if (hasAssociatedText())
+ {
+ int extra;
+
+ int textLength = getAssociatedTextLength();
+ if (textLength < ((1 << 16) - (1 << 8)))
+ {
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 2;
+ }
+ else // can't go any higher than 2^32
+ {
+ cMac.update((byte)0xff);
+ cMac.update((byte)0xfe);
+ cMac.update((byte)(textLength >> 24));
+ cMac.update((byte)(textLength >> 16));
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 6;
+ }
+
+ 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 = extra; i != 16; i++)
+ {
+ cMac.update((byte)0x00);
+ }
+ }
+ }
+
+ //
+ // add the text
+ //
+ cMac.update(data, dataOff, dataLen);
+
+ return cMac.doFinal(macBlock, 0);
+ }
+
+ private int getAssociatedTextLength()
+ {
+ return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
+ }
+
+ private boolean hasAssociatedText()
+ {
+ return getAssociatedTextLength() > 0;
+ }
+}
diff --git a/src/main/java/org/bouncycastle/crypto/util/Pack.java b/src/main/java/org/bouncycastle/crypto/util/Pack.java
index b767cc9e..d2ce166b 100644
--- a/src/main/java/org/bouncycastle/crypto/util/Pack.java
+++ b/src/main/java/org/bouncycastle/crypto/util/Pack.java
@@ -1,192 +1,192 @@
-package org.bouncycastle.crypto.util;
-
-public abstract class Pack
-{
- public static int bigEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] << 24;
- n |= (bs[++off] & 0xff) << 16;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff);
- return n;
- }
-
- public static void bigEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static byte[] intToBigEndian(int n)
- {
- byte[] bs = new byte[4];
- intToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n >>> 24);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n );
- }
-
- public static byte[] intToBigEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToBigEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToBigEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long bigEndianToLong(byte[] bs, int off)
- {
- int hi = bigEndianToInt(bs, off);
- int lo = bigEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void bigEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = bigEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToBigEndian(long n)
- {
- byte[] bs = new byte[8];
- longToBigEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long n, byte[] bs, int off)
- {
- intToBigEndian((int)(n >>> 32), bs, off);
- intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
- }
-
- public static byte[] longToBigEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToBigEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToBigEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToBigEndian(ns[i], bs, off);
- off += 8;
- }
- }
-
- public static int littleEndianToInt(byte[] bs, int off)
- {
- int n = bs[ off] & 0xff;
- n |= (bs[++off] & 0xff) << 8;
- n |= (bs[++off] & 0xff) << 16;
- n |= bs[++off] << 24;
- return n;
- }
-
- public static void littleEndianToInt(byte[] bs, int off, int[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToInt(bs, off);
- off += 4;
- }
- }
-
- public static byte[] intToLittleEndian(int n)
- {
- byte[] bs = new byte[4];
- intToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int n, byte[] bs, int off)
- {
- bs[ off] = (byte)(n );
- bs[++off] = (byte)(n >>> 8);
- bs[++off] = (byte)(n >>> 16);
- bs[++off] = (byte)(n >>> 24);
- }
-
- public static byte[] intToLittleEndian(int[] ns)
- {
- byte[] bs = new byte[4 * ns.length];
- intToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void intToLittleEndian(int[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- intToLittleEndian(ns[i], bs, off);
- off += 4;
- }
- }
-
- public static long littleEndianToLong(byte[] bs, int off)
- {
- int lo = littleEndianToInt(bs, off);
- int hi = littleEndianToInt(bs, off + 4);
- return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
- }
-
- public static void littleEndianToLong(byte[] bs, int off, long[] ns)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- ns[i] = littleEndianToLong(bs, off);
- off += 8;
- }
- }
-
- public static byte[] longToLittleEndian(long n)
- {
- byte[] bs = new byte[8];
- longToLittleEndian(n, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long n, byte[] bs, int off)
- {
- intToLittleEndian((int)(n & 0xffffffffL), bs, off);
- intToLittleEndian((int)(n >>> 32), bs, off + 4);
- }
-
- public static byte[] longToLittleEndian(long[] ns)
- {
- byte[] bs = new byte[8 * ns.length];
- longToLittleEndian(ns, bs, 0);
- return bs;
- }
-
- public static void longToLittleEndian(long[] ns, byte[] bs, int off)
- {
- for (int i = 0; i < ns.length; ++i)
- {
- longToLittleEndian(ns[i], bs, off);
- off += 8;
- }
- }
-}
+package org.bouncycastle.crypto.util;
+
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void bigEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static byte[] intToBigEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n >>> 24);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n );
+ }
+
+ public static byte[] intToBigEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToBigEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToBigEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long bigEndianToLong(byte[] bs, int off)
+ {
+ int hi = bigEndianToInt(bs, off);
+ int lo = bigEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void bigEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToBigEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToBigEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+
+ public static byte[] longToBigEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToBigEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToBigEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToBigEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+
+ public static int littleEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ public static void littleEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static byte[] intToLittleEndian(int n)
+ {
+ byte[] bs = new byte[4];
+ intToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n );
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 24);
+ }
+
+ public static byte[] intToLittleEndian(int[] ns)
+ {
+ byte[] bs = new byte[4 * ns.length];
+ intToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void intToLittleEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToLittleEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long littleEndianToLong(byte[] bs, int off)
+ {
+ int lo = littleEndianToInt(bs, off);
+ int hi = littleEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void littleEndianToLong(byte[] bs, int off, long[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToLong(bs, off);
+ off += 8;
+ }
+ }
+
+ public static byte[] longToLittleEndian(long n)
+ {
+ byte[] bs = new byte[8];
+ longToLittleEndian(n, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long n, byte[] bs, int off)
+ {
+ intToLittleEndian((int)(n & 0xffffffffL), bs, off);
+ intToLittleEndian((int)(n >>> 32), bs, off + 4);
+ }
+
+ public static byte[] longToLittleEndian(long[] ns)
+ {
+ byte[] bs = new byte[8 * ns.length];
+ longToLittleEndian(ns, bs, 0);
+ return bs;
+ }
+
+ public static void longToLittleEndian(long[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ longToLittleEndian(ns[i], bs, off);
+ off += 8;
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/src/main/java/org/bouncycastle/math/ec/ECPoint.java
index ac67152a..cbc5aaf4 100644
--- a/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -1,593 +1,593 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-
-/**
- * base class for points on elliptic curves.
- */
-public abstract class ECPoint
-{
- ECCurve curve;
- ECFieldElement x;
- ECFieldElement y;
-
- protected boolean withCompression;
-
- protected ECMultiplier multiplier = null;
-
- protected PreCompInfo preCompInfo = null;
-
- private static X9IntegerConverter converter = new X9IntegerConverter();
-
- protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this.curve = curve;
- this.x = x;
- this.y = y;
- }
-
- public ECCurve getCurve()
- {
- return curve;
- }
-
- public ECFieldElement getX()
- {
- return x;
- }
-
- public ECFieldElement getY()
- {
- return y;
- }
-
- public boolean isInfinity()
- {
- return x == null && y == null;
- }
-
- public boolean isCompressed()
- {
- return withCompression;
- }
-
- public boolean equals(
- Object other)
- {
- if (other == this)
- {
- return true;
- }
-
- if (!(other instanceof ECPoint))
- {
- return false;
- }
-
- ECPoint o = (ECPoint)other;
-
- if (this.isInfinity())
- {
- return o.isInfinity();
- }
-
- return x.equals(o.x) && y.equals(o.y);
- }
-
- public int hashCode()
- {
- if (this.isInfinity())
- {
- return 0;
- }
-
- return x.hashCode() ^ y.hashCode();
- }
-
-// /**
-// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
-// * @param multiplier The <code>ECMultiplier</code> to be used to multiply
-// * this <code>ECPoint</code>.
-// */
-// public void setECMultiplier(ECMultiplier multiplier)
-// {
-// this.multiplier = multiplier;
-// }
-
- /**
- * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
- * to save the precomputation for this <code>ECPoint</code> to store the
- * precomputation result for use by subsequent multiplication.
- * @param preCompInfo The values precomputed by the
- * <code>ECMultiplier</code>.
- */
- void setPreCompInfo(PreCompInfo preCompInfo)
- {
- this.preCompInfo = preCompInfo;
- }
-
- public byte[] getEncoded()
- {
- return getEncoded(withCompression);
- }
-
- public abstract byte[] getEncoded(boolean compressed);
-
- public abstract ECPoint add(ECPoint b);
- public abstract ECPoint subtract(ECPoint b);
- public abstract ECPoint negate();
- public abstract ECPoint twice();
-
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
- {
- if (this.multiplier == null)
- {
- this.multiplier = new FpNafMultiplier();
- }
- }
-
- /**
- * Multiplies this <code>ECPoint</code> by the given number.
- * @param k The multiplicator.
- * @return <code>k * this</code>.
- */
- public ECPoint multiply(BigInteger k)
- {
- if (k.signum() < 0)
- {
- throw new IllegalArgumentException("The multiplicator cannot be negative");
- }
-
- if (this.isInfinity())
- {
- return this;
- }
-
- if (k.signum() == 0)
- {
- return this.curve.getInfinity();
- }
-
- assertECMultiplier();
- return this.multiplier.multiply(this, k, preCompInfo);
- }
-
- /**
- * Elliptic curve points over Fp
- */
- public static class Fp extends ECPoint
- {
-
- /**
- * Create a point which encodes with point compression.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * Create a point that encodes with or without point compresion.
- *
- * @param curve the curve to use
- * @param x affine x co-ordinate
- * @param y affine y co-ordinate
- * @param withCompression if true encode with point compression
- */
- public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- this.withCompression = withCompression;
- }
-
- /**
- * return the field element encoded with point compression. (S 4.3.6)
- */
- public byte[] getEncoded(boolean compressed)
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- int qLength = converter.getByteLength(x);
-
- if (compressed)
- {
- byte PC;
-
- if (this.getY().toBigInteger().testBit(0))
- {
- PC = 0x03;
- }
- else
- {
- PC = 0x02;
- }
-
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + 1];
-
- PO[0] = PC;
- System.arraycopy(X, 0, PO, 1, X.length);
-
- return PO;
- }
- else
- {
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
- byte[] PO = new byte[X.length + Y.length + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, X.length);
- System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
-
- return PO;
- }
- }
-
- // B.3 pg 62
- public ECPoint add(ECPoint b)
- {
- if (this.isInfinity())
- {
- return b;
- }
-
- if (b.isInfinity())
- {
- return this;
- }
-
- // Check if b = this or b = -this
- if (this.x.equals(b.x))
- {
- if (this.y.equals(b.y))
- {
- // this = b, i.e. this must be doubled
- return this.twice();
- }
-
- // this = -b, i.e. the result is the point at infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
-
- ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3, withCompression);
- }
-
- // B.3 pg 62
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- // Twice identity element (point at infinity) is identity
- return this;
- }
-
- if (this.y.toBigInteger().signum() == 0)
- {
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
- ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
- ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
-
- ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
- ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPoint.Fp(curve, x3, y3, this.withCompression);
- }
-
- // D.3.2 pg 102 (see Note:)
- public ECPoint subtract(ECPoint b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return add(b.negate());
- }
-
- public ECPoint negate()
- {
- return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
- }
-
- /**
- * Sets the default <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
- {
- if (this.multiplier == null)
- {
- this.multiplier = new WNafMultiplier();
- }
- }
- }
-
- /**
- * Elliptic curve points over F2m
- */
- public static class F2m extends ECPoint
- {
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
- {
- this(curve, x, y, false);
- }
-
- /**
- * @param curve base curve
- * @param x x point
- * @param y y point
- * @param withCompression true if encode with point compression.
- */
- public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
- {
- super(curve, x, y);
-
- if ((x != null && y == null) || (x == null && y != null))
- {
- throw new IllegalArgumentException("Exactly one of the field elements is null");
- }
-
- if (x != null)
- {
- // Check if x and y are elements of the same field
- ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-
- // Check if x and a are elements of the same field
- if (curve != null)
- {
- ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
- }
- }
-
- this.withCompression = withCompression;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
- */
- public byte[] getEncoded(boolean compressed)
- {
- if (this.isInfinity())
- {
- return new byte[1];
- }
-
- int byteCount = converter.getByteLength(this.x);
- byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
- byte[] PO;
-
- if (compressed)
- {
- // See X9.62 4.3.6 and 4.2.2
- PO = new byte[byteCount + 1];
-
- PO[0] = 0x02;
- // X9.62 4.2.2 and 4.3.6:
- // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
- // bit of y * x^(-1)
- // if ypTilde = 0, then PC := 02, else PC := 03
- // Note: PC === PO[0]
- if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
- {
- if (this.getY().multiply(this.getX().invert())
- .toBigInteger().testBit(0))
- {
- // ypTilde = 1, hence PC = 03
- PO[0] = 0x03;
- }
- }
-
- System.arraycopy(X, 0, PO, 1, byteCount);
- }
- else
- {
- byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
-
- PO = new byte[byteCount + byteCount + 1];
-
- PO[0] = 0x04;
- System.arraycopy(X, 0, PO, 1, byteCount);
- System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
- }
-
- return PO;
- }
-
- /**
- * Check, if two <code>ECPoint</code>s can be added or subtracted.
- * @param a The first <code>ECPoint</code> to check.
- * @param b The second <code>ECPoint</code> to check.
- * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
- * cannot be added.
- */
- private static void checkPoints(ECPoint a, ECPoint b)
- {
- // Check, if points are on the same curve
- if (!(a.curve.equals(b.curve)))
- {
- throw new IllegalArgumentException("Only points on the same "
- + "curve can be added or subtracted");
- }
-
-// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint add(ECPoint b)
- {
- checkPoints(this, b);
- return addSimple((ECPoint.F2m)b);
- }
-
- /**
- * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
- * checking if both points are on the same curve. Used by multiplication
- * algorithms, because there all points are a multiple of the same point
- * and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to add to
- * <code>this</code>.
- * @return <code>this + b</code>
- */
- public ECPoint.F2m addSimple(ECPoint.F2m b)
- {
- ECPoint.F2m other = b;
- if (this.isInfinity())
- {
- return other;
- }
-
- if (other.isInfinity())
- {
- return this;
- }
-
- ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
- ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
-
- // Check if other = this or other = -this
- if (this.x.equals(x2))
- {
- if (this.y.equals(y2))
- {
- // this = other, i.e. this must be doubled
- return (ECPoint.F2m)this.twice();
- }
-
- // this = -other, i.e. the result is the point at infinity
- return (ECPoint.F2m)this.curve.getInfinity();
- }
-
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
-
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
-
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
-
- return new ECPoint.F2m(curve, x3, y3, withCompression);
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
- */
- public ECPoint subtract(ECPoint b)
- {
- checkPoints(this, b);
- return subtractSimple((ECPoint.F2m)b);
- }
-
- /**
- * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
- * without checking if both points are on the same curve. Used by
- * multiplication algorithms, because there all points are a multiple
- * of the same point and hence the checks can be omitted.
- * @param b The other <code>ECPoints.F2m</code> to subtract from
- * <code>this</code>.
- * @return <code>this - b</code>
- */
- public ECPoint.F2m subtractSimple(ECPoint.F2m b)
- {
- if (b.isInfinity())
- {
- return this;
- }
-
- // Add -b
- return addSimple((ECPoint.F2m)b.negate());
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.math.ec.ECPoint#twice()
- */
- public ECPoint twice()
- {
- if (this.isInfinity())
- {
- // Twice identity element (point at infinity) is identity
- return this;
- }
-
- if (this.x.toBigInteger().signum() == 0)
- {
- // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
- }
-
- ECFieldElement.F2m lambda
- = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
-
- ECFieldElement.F2m x3
- = (ECFieldElement.F2m)lambda.square().add(lambda).
- add(this.curve.getA());
-
- ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
- ECFieldElement.F2m y3
- = (ECFieldElement.F2m)this.x.square().add(
- x3.multiply(lambda.add(ONE)));
-
- return new ECPoint.F2m(this.curve, x3, y3, withCompression);
- }
-
- public ECPoint negate()
- {
- return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
- }
-
- /**
- * Sets the appropriate <code>ECMultiplier</code>, unless already set.
- */
- synchronized void assertECMultiplier()
- {
- if (this.multiplier == null)
- {
- if (((ECCurve.F2m)this.curve).isKoblitz())
- {
- this.multiplier = new WTauNafMultiplier();
- }
- else
- {
- this.multiplier = new WNafMultiplier();
- }
- }
- }
- }
-}
+package org.bouncycastle.math.ec;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.x9.X9IntegerConverter;
+
+/**
+ * base class for points on elliptic curves.
+ */
+public abstract class ECPoint
+{
+ ECCurve curve;
+ ECFieldElement x;
+ ECFieldElement y;
+
+ protected boolean withCompression;
+
+ protected ECMultiplier multiplier = null;
+
+ protected PreCompInfo preCompInfo = null;
+
+ private static X9IntegerConverter converter = new X9IntegerConverter();
+
+ protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this.curve = curve;
+ this.x = x;
+ this.y = y;
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public ECFieldElement getX()
+ {
+ return x;
+ }
+
+ public ECFieldElement getY()
+ {
+ return y;
+ }
+
+ public boolean isInfinity()
+ {
+ return x == null && y == null;
+ }
+
+ public boolean isCompressed()
+ {
+ return withCompression;
+ }
+
+ public boolean equals(
+ Object other)
+ {
+ if (other == this)
+ {
+ return true;
+ }
+
+ if (!(other instanceof ECPoint))
+ {
+ return false;
+ }
+
+ ECPoint o = (ECPoint)other;
+
+ if (this.isInfinity())
+ {
+ return o.isInfinity();
+ }
+
+ return x.equals(o.x) && y.equals(o.y);
+ }
+
+ public int hashCode()
+ {
+ if (this.isInfinity())
+ {
+ return 0;
+ }
+
+ return x.hashCode() ^ y.hashCode();
+ }
+
+// /**
+// * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
+// * @param multiplier The <code>ECMultiplier</code> to be used to multiply
+// * this <code>ECPoint</code>.
+// */
+// public void setECMultiplier(ECMultiplier multiplier)
+// {
+// this.multiplier = multiplier;
+// }
+
+ /**
+ * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
+ * to save the precomputation for this <code>ECPoint</code> to store the
+ * precomputation result for use by subsequent multiplication.
+ * @param preCompInfo The values precomputed by the
+ * <code>ECMultiplier</code>.
+ */
+ void setPreCompInfo(PreCompInfo preCompInfo)
+ {
+ this.preCompInfo = preCompInfo;
+ }
+
+ public byte[] getEncoded()
+ {
+ return getEncoded(withCompression);
+ }
+
+ public abstract byte[] getEncoded(boolean compressed);
+
+ public abstract ECPoint add(ECPoint b);
+ public abstract ECPoint subtract(ECPoint b);
+ public abstract ECPoint negate();
+ public abstract ECPoint twice();
+
+ /**
+ * Sets the default <code>ECMultiplier</code>, unless already set.
+ */
+ synchronized void assertECMultiplier()
+ {
+ if (this.multiplier == null)
+ {
+ this.multiplier = new FpNafMultiplier();
+ }
+ }
+
+ /**
+ * Multiplies this <code>ECPoint</code> by the given number.
+ * @param k The multiplicator.
+ * @return <code>k * this</code>.
+ */
+ public ECPoint multiply(BigInteger k)
+ {
+ if (k.signum() < 0)
+ {
+ throw new IllegalArgumentException("The multiplicator cannot be negative");
+ }
+
+ if (this.isInfinity())
+ {
+ return this;
+ }
+
+ if (k.signum() == 0)
+ {
+ return this.curve.getInfinity();
+ }
+
+ assertECMultiplier();
+ return this.multiplier.multiply(this, k, preCompInfo);
+ }
+
+ /**
+ * Elliptic curve points over Fp
+ */
+ public static class Fp extends ECPoint
+ {
+
+ /**
+ * Create a point which encodes with point compression.
+ *
+ * @param curve the curve to use
+ * @param x affine x co-ordinate
+ * @param y affine y co-ordinate
+ */
+ public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * Create a point that encodes with or without point compresion.
+ *
+ * @param curve the curve to use
+ * @param x affine x co-ordinate
+ * @param y affine y co-ordinate
+ * @param withCompression if true encode with point compression
+ */
+ public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x != null && y == null) || (x == null && y != null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ /**
+ * return the field element encoded with point compression. (S 4.3.6)
+ */
+ public byte[] getEncoded(boolean compressed)
+ {
+ if (this.isInfinity())
+ {
+ return new byte[1];
+ }
+
+ int qLength = converter.getByteLength(x);
+
+ if (compressed)
+ {
+ byte PC;
+
+ if (this.getY().toBigInteger().testBit(0))
+ {
+ PC = 0x03;
+ }
+ else
+ {
+ PC = 0x02;
+ }
+
+ byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
+ byte[] PO = new byte[X.length + 1];
+
+ PO[0] = PC;
+ System.arraycopy(X, 0, PO, 1, X.length);
+
+ return PO;
+ }
+ else
+ {
+ byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
+ byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
+ byte[] PO = new byte[X.length + Y.length + 1];
+
+ PO[0] = 0x04;
+ System.arraycopy(X, 0, PO, 1, X.length);
+ System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
+
+ return PO;
+ }
+ }
+
+ // B.3 pg 62
+ public ECPoint add(ECPoint b)
+ {
+ if (this.isInfinity())
+ {
+ return b;
+ }
+
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Check if b = this or b = -this
+ if (this.x.equals(b.x))
+ {
+ if (this.y.equals(b.y))
+ {
+ // this = b, i.e. this must be doubled
+ return this.twice();
+ }
+
+ // this = -b, i.e. the result is the point at infinity
+ return this.curve.getInfinity();
+ }
+
+ ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
+
+ ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
+ ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
+
+ return new ECPoint.Fp(curve, x3, y3, withCompression);
+ }
+
+ // B.3 pg 62
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ // Twice identity element (point at infinity) is identity
+ return this;
+ }
+
+ if (this.y.toBigInteger().signum() == 0)
+ {
+ // if y1 == 0, then (x1, y1) == (x1, -y1)
+ // and hence this = -this and thus 2(x1, y1) == infinity
+ return this.curve.getInfinity();
+ }
+
+ ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
+ ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
+ ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
+
+ ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
+ ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
+
+ return new ECPoint.Fp(curve, x3, y3, this.withCompression);
+ }
+
+ // D.3.2 pg 102 (see Note:)
+ public ECPoint subtract(ECPoint b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return add(b.negate());
+ }
+
+ public ECPoint negate()
+ {
+ return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
+ }
+
+ /**
+ * Sets the default <code>ECMultiplier</code>, unless already set.
+ */
+ synchronized void assertECMultiplier()
+ {
+ if (this.multiplier == null)
+ {
+ this.multiplier = new WNafMultiplier();
+ }
+ }
+ }
+
+ /**
+ * Elliptic curve points over F2m
+ */
+ public static class F2m extends ECPoint
+ {
+ /**
+ * @param curve base curve
+ * @param x x point
+ * @param y y point
+ */
+ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
+ {
+ this(curve, x, y, false);
+ }
+
+ /**
+ * @param curve base curve
+ * @param x x point
+ * @param y y point
+ * @param withCompression true if encode with point compression.
+ */
+ public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
+ {
+ super(curve, x, y);
+
+ if ((x != null && y == null) || (x == null && y != null))
+ {
+ throw new IllegalArgumentException("Exactly one of the field elements is null");
+ }
+
+ if (x != null)
+ {
+ // Check if x and y are elements of the same field
+ ECFieldElement.F2m.checkFieldElements(this.x, this.y);
+
+ // Check if x and a are elements of the same field
+ if (curve != null)
+ {
+ ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
+ }
+ }
+
+ this.withCompression = withCompression;
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
+ */
+ public byte[] getEncoded(boolean compressed)
+ {
+ if (this.isInfinity())
+ {
+ return new byte[1];
+ }
+
+ int byteCount = converter.getByteLength(this.x);
+ byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
+ byte[] PO;
+
+ if (compressed)
+ {
+ // See X9.62 4.3.6 and 4.2.2
+ PO = new byte[byteCount + 1];
+
+ PO[0] = 0x02;
+ // X9.62 4.2.2 and 4.3.6:
+ // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
+ // bit of y * x^(-1)
+ // if ypTilde = 0, then PC := 02, else PC := 03
+ // Note: PC === PO[0]
+ if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
+ {
+ if (this.getY().multiply(this.getX().invert())
+ .toBigInteger().testBit(0))
+ {
+ // ypTilde = 1, hence PC = 03
+ PO[0] = 0x03;
+ }
+ }
+
+ System.arraycopy(X, 0, PO, 1, byteCount);
+ }
+ else
+ {
+ byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
+
+ PO = new byte[byteCount + byteCount + 1];
+
+ PO[0] = 0x04;
+ System.arraycopy(X, 0, PO, 1, byteCount);
+ System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);
+ }
+
+ return PO;
+ }
+
+ /**
+ * Check, if two <code>ECPoint</code>s can be added or subtracted.
+ * @param a The first <code>ECPoint</code> to check.
+ * @param b The second <code>ECPoint</code> to check.
+ * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+ * cannot be added.
+ */
+ private static void checkPoints(ECPoint a, ECPoint b)
+ {
+ // Check, if points are on the same curve
+ if (!(a.curve.equals(b.curve)))
+ {
+ throw new IllegalArgumentException("Only points on the same "
+ + "curve can be added or subtracted");
+ }
+
+// ECFieldElement.F2m.checkFieldElements(a.x, b.x);
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
+ */
+ public ECPoint add(ECPoint b)
+ {
+ checkPoints(this, b);
+ return addSimple((ECPoint.F2m)b);
+ }
+
+ /**
+ * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
+ * checking if both points are on the same curve. Used by multiplication
+ * algorithms, because there all points are a multiple of the same point
+ * and hence the checks can be omitted.
+ * @param b The other <code>ECPoints.F2m</code> to add to
+ * <code>this</code>.
+ * @return <code>this + b</code>
+ */
+ public ECPoint.F2m addSimple(ECPoint.F2m b)
+ {
+ ECPoint.F2m other = b;
+ if (this.isInfinity())
+ {
+ return other;
+ }
+
+ if (other.isInfinity())
+ {
+ return this;
+ }
+
+ ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
+ ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
+
+ // Check if other = this or other = -this
+ if (this.x.equals(x2))
+ {
+ if (this.y.equals(y2))
+ {
+ // this = other, i.e. this must be doubled
+ return (ECPoint.F2m)this.twice();
+ }
+
+ // this = -other, i.e. the result is the point at infinity
+ return (ECPoint.F2m)this.curve.getInfinity();
+ }
+
+ ECFieldElement.F2m lambda
+ = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
+
+ ECFieldElement.F2m x3
+ = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
+
+ ECFieldElement.F2m y3
+ = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
+
+ return new ECPoint.F2m(curve, x3, y3, withCompression);
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
+ */
+ public ECPoint subtract(ECPoint b)
+ {
+ checkPoints(this, b);
+ return subtractSimple((ECPoint.F2m)b);
+ }
+
+ /**
+ * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
+ * without checking if both points are on the same curve. Used by
+ * multiplication algorithms, because there all points are a multiple
+ * of the same point and hence the checks can be omitted.
+ * @param b The other <code>ECPoints.F2m</code> to subtract from
+ * <code>this</code>.
+ * @return <code>this - b</code>
+ */
+ public ECPoint.F2m subtractSimple(ECPoint.F2m b)
+ {
+ if (b.isInfinity())
+ {
+ return this;
+ }
+
+ // Add -b
+ return addSimple((ECPoint.F2m)b.negate());
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.math.ec.ECPoint#twice()
+ */
+ public ECPoint twice()
+ {
+ if (this.isInfinity())
+ {
+ // Twice identity element (point at infinity) is identity
+ return this;
+ }
+
+ if (this.x.toBigInteger().signum() == 0)
+ {
+ // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
+ // and hence this = -this and thus 2(x1, y1) == infinity
+ return this.curve.getInfinity();
+ }
+
+ ECFieldElement.F2m lambda
+ = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
+
+ ECFieldElement.F2m x3
+ = (ECFieldElement.F2m)lambda.square().add(lambda).
+ add(this.curve.getA());
+
+ ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
+ ECFieldElement.F2m y3
+ = (ECFieldElement.F2m)this.x.square().add(
+ x3.multiply(lambda.add(ONE)));
+
+ return new ECPoint.F2m(this.curve, x3, y3, withCompression);
+ }
+
+ public ECPoint negate()
+ {
+ return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
+ }
+
+ /**
+ * Sets the appropriate <code>ECMultiplier</code>, unless already set.
+ */
+ synchronized void assertECMultiplier()
+ {
+ if (this.multiplier == null)
+ {
+ if (((ECCurve.F2m)this.curve).isKoblitz())
+ {
+ this.multiplier = new WTauNafMultiplier();
+ }
+ else
+ {
+ this.multiplier = new WNafMultiplier();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/bouncycastle/util/encoders/Base64.java b/src/main/java/org/bouncycastle/util/encoders/Base64.java
index 9b7d0e43..83806295 100644
--- a/src/main/java/org/bouncycastle/util/encoders/Base64.java
+++ b/src/main/java/org/bouncycastle/util/encoders/Base64.java
@@ -1,151 +1,151 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.util.Strings;
-
-public class Base64
-{
- private static final Encoder encoder = new Base64Encoder();
-
- public static String toBase64String(
- byte[] data)
- {
- return toBase64String(data, 0, data.length);
- }
-
- public static String toBase64String(
- byte[] data,
- int off,
- int length)
- {
- byte[] encoded = encode(data, off, length);
- return Strings.fromByteArray(encoded);
- }
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- *
- * @return a byte array containing the base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- return encode(data, 0, data.length);
- }
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- *
- * @return a byte array containing the base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data,
- int off,
- int length)
- {
- int len = (length + 2) / 3 * 4;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.encode(data, off, length, bOut);
- }
- catch (Exception e)
- {
- throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the base 64 encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- int len = data.length / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- int len = data.length() / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
+package org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Strings;
+
+public class Base64
+{
+ private static final Encoder encoder = new Base64Encoder();
+
+ public static String toBase64String(
+ byte[] data)
+ {
+ return toBase64String(data, 0, data.length);
+ }
+
+ public static String toBase64String(
+ byte[] data,
+ int off,
+ int length)
+ {
+ byte[] encoded = encode(data, off, length);
+ return Strings.fromByteArray(encoded);
+ }
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ *
+ * @return a byte array containing the base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ *
+ * @return a byte array containing the base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ int len = (length + 2) / 3 * 4;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the base 64 encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ int len = data.length / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ int len = data.length() / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff --git a/src/main/java/org/bouncycastle/util/encoders/Hex.java b/src/main/java/org/bouncycastle/util/encoders/Hex.java
index 6a1c0f8e..d49f1ef4 100644
--- a/src/main/java/org/bouncycastle/util/encoders/Hex.java
+++ b/src/main/java/org/bouncycastle/util/encoders/Hex.java
@@ -1,148 +1,148 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.bouncycastle.util.Strings;
-
-public class Hex
-{
- private static final Encoder encoder = new HexEncoder();
-
- public static String toHexString(
- byte[] data)
- {
- return toHexString(data, 0, data.length);
- }
-
- public static String toHexString(
- byte[] data,
- int off,
- int length)
- {
- byte[] encoded = encode(data, off, length);
- return Strings.fromByteArray(encoded);
- }
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- return encode(data, 0, data.length);
- }
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data,
- int off,
- int length)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.encode(data, off, length, bOut);
- }
- catch (Exception e)
- {
- throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the Hex encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (Exception e)
- {
- throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
+package org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.bouncycastle.util.Strings;
+
+public class Hex
+{
+ private static final Encoder encoder = new HexEncoder();
+
+ public static String toHexString(
+ byte[] data)
+ {
+ return toHexString(data, 0, data.length);
+ }
+
+ public static String toHexString(
+ byte[] data,
+ int off,
+ int length)
+ {
+ byte[] encoded = encode(data, off, length);
+ return Strings.fromByteArray(encoded);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the Hex encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}