From 274013ad68bdad05c47c881b539fd3e5404af99f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=AD?=
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
diff --git a/extern/spongycastle/build.gradle b/extern/spongycastle/build.gradle
index d43c6d0c5..026a1b2be 100644
--- a/extern/spongycastle/build.gradle
+++ b/extern/spongycastle/build.gradle
@@ -9,5 +9,5 @@ subprojects {
sourceCompatibility = 1.5
targetCompatibility = 1.5
- version = '1.50.0.0'
+ version = '1.51.0.0'
}
diff --git a/extern/spongycastle/core/build.gradle b/extern/spongycastle/core/build.gradle
index b7da23bfe..f467548dc 100644
--- a/extern/spongycastle/core/build.gradle
+++ b/extern/spongycastle/core/build.gradle
@@ -2,4 +2,4 @@ apply plugin: 'java'
sourceCompatibility = 1.5
targetCompatibility = 1.5
-version = '1.50.0.0'
+version = '1.51.0.0'
diff --git a/extern/spongycastle/core/src/main/j2me/java/math/BigInteger.java b/extern/spongycastle/core/src/main/j2me/java/math/BigInteger.java
index 9017caa01..fb59fad40 100644
--- a/extern/spongycastle/core/src/main/j2me/java/math/BigInteger.java
+++ b/extern/spongycastle/core/src/main/j2me/java/math/BigInteger.java
@@ -1460,11 +1460,11 @@ public class BigInteger
bitsCorrect <<= 1;
}
while (bitsCorrect < pow);
+ }
- if (x.sign < 0)
- {
- x = x.add(m);
- }
+ if (x.sign < 0)
+ {
+ x = x.add(m);
}
return x;
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java
index 0fa3440a7..919b0f6e5 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1GeneralizedTime.java
@@ -1,27 +1,260 @@
package org.spongycastle.asn1;
+import java.io.IOException;
import java.util.Date;
+import java.util.TimeZone;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * Generalized time object.
+ */
public class ASN1GeneralizedTime
- extends DERGeneralizedTime
+ extends ASN1Primitive
{
- ASN1GeneralizedTime(byte[] bytes)
+ private byte[] time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ Object obj)
{
- super(bytes);
+ if (obj == null || obj instanceof ASN1GeneralizedTime)
+ {
+ return (ASN1GeneralizedTime)obj;
+ }
+
+ if (obj instanceof ASN1GeneralizedTime)
+ {
+ return new ASN1GeneralizedTime(((ASN1GeneralizedTime)obj).time);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
- public ASN1GeneralizedTime(Date date)
+ /**
+ * return a Generalized Time object 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 ASN1GeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
{
- super(date);
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1GeneralizedTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z|[+|-]HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @exception IllegalArgumentException if String is an illegal format.
+ */
+ public ASN1GeneralizedTime(
+ String time)
+ {
+ char last = time.charAt(time.length() - 1);
+ if (last != 'Z' && !(last >= 0 && last <= '9'))
+ {
+ if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
+ {
+ throw new IllegalArgumentException("time needs to be in format YYYYMMDDHHMMSS[.f]Z or YYYYMMDDHHMMSS[.f][+-]HHMM");
+ }
+ }
+
+ this.time = Strings.toByteArray(time);
}
- public ASN1GeneralizedTime(Date date, boolean includeMillis)
+ /**
+ * base constructer from a java.util.date object
+ */
+ public ASN1GeneralizedTime(
+ Date time)
{
- super(date, includeMillis);
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
}
- public ASN1GeneralizedTime(String time)
+ protected ASN1GeneralizedTime(Date date, boolean includeMillis)
{
- super(time);
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
+ }
+
+ ASN1GeneralizedTime(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ *
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ *
+ *
+ * @param time the time string.
+ */
+ public ASN1UTCTime(
+ String time)
+ {
+ if (time.charAt(time.length() - 1) != 'Z')
+ {
+ // we accept this as a variation
+ if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
+ {
+ throw new IllegalArgumentException("time needs to be in format YYMMDDHHMMSSZ");
+ }
+ }
+
+ this.time = Strings.toByteArray(time);
}
- public ASN1UTCTime(String time)
+ /**
+ * base constructor from a java.util.date object
+ */
+ public ASN1UTCTime(
+ Date time)
{
- super(time);
+ this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
+ }
+
+ ASN1UTCTime(
+ byte[] time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ */
+ public Date getDate()
+ {
+ return DateFormatter.adjustedFromUTCDateString(time);
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ */
+ public Date getAdjustedDate()
+ {
+ return DateFormatter.adjustedFromUTCDateString(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ *
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ *
+ * Note: In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the getAdjustedTime() method.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
+ {
+ if (stime.length() == 11)
+ {
+ return stime.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return stime.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = stime.indexOf('-');
+ if (index < 0)
+ {
+ index = stime.indexOf('+');
+ }
+ String d = stime;
+
+ if (index == stime.length() - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+ }
+ else
+ {
+ return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+ }
+ }
+ }
+
+ /**
+ * return a time string as an adjusted date with a 4 digit year. This goes
+ * in the range of 1950 - 2049.
+ */
+ public String getAdjustedTime()
+ {
+ String d = this.getTime();
+
+ if (d.charAt(0) < '5')
+ {
+ return "20" + d;
+ }
+ else
+ {
+ return "19" + d;
+ }
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.UTC_TIME);
+
+ int length = time.length;
+
+ out.writeLength(length);
+
+ for (int i = 0; i != length; i++)
+ {
+ out.write((byte)time[i]);
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1UTCTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public String toString()
+ {
+ return Strings.fromByteArray(time);
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java
index 82b780375..51eee45e3 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERGeneralizedTime.java
@@ -1,260 +1,27 @@
package org.spongycastle.asn1;
-import java.io.IOException;
import java.util.Date;
-import java.util.TimeZone;
-import org.spongycastle.util.Arrays;
-import org.spongycastle.util.Strings;
-
-/**
- * Generalized time object.
- */
public class DERGeneralizedTime
- extends ASN1Primitive
+ extends ASN1GeneralizedTime
{
- private byte[] time;
-
- /**
- * return a generalized time from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1GeneralizedTime getInstance(
- Object obj)
+ DERGeneralizedTime(byte[] bytes)
{
- if (obj == null || obj instanceof ASN1GeneralizedTime)
- {
- return (ASN1GeneralizedTime)obj;
- }
-
- if (obj instanceof DERGeneralizedTime)
- {
- return new ASN1GeneralizedTime(((DERGeneralizedTime)obj).time);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ super(bytes);
}
- /**
- * return a Generalized Time object 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 ASN1GeneralizedTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
+ public DERGeneralizedTime(Date date)
{
- ASN1Primitive o = obj.getObject();
-
- if (explicit || o instanceof DERGeneralizedTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
- * for local time, or Z|[+|-]HHMM on the end, for difference between local
- * time and UTC time. The fractional second amount f must consist of at
- * least one number with trailing zeroes removed.
- *
- * @param time the time string.
- * @exception IllegalArgumentException if String is an illegal format.
- */
- public DERGeneralizedTime(
- String time)
- {
- char last = time.charAt(time.length() - 1);
- if (last != 'Z' && !(last >= 0 && last <= '9'))
- {
- if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
- {
- throw new IllegalArgumentException("time needs to be in format YYYYMMDDHHMMSS[.f]Z or YYYYMMDDHHMMSS[.f][+-]HHMM");
- }
- }
-
- this.time = Strings.toByteArray(time);
+ super(date);
}
- /**
- * base constructer from a java.util.date object
- */
- public DERGeneralizedTime(
- Date time)
+ public DERGeneralizedTime(Date date, boolean includeMillis)
{
- this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
+ super(date, includeMillis);
}
- protected DERGeneralizedTime(Date date, boolean includeMillis)
+ public DERGeneralizedTime(String time)
{
- this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
- }
-
- DERGeneralizedTime(
- byte[] bytes)
- {
- this.time = bytes;
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- /**
- * return the time - always in the form of
- * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- *
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- *
- *
- * @param time the time string.
- */
- public DERUTCTime(
- String time)
- {
- if (time.charAt(time.length() - 1) != 'Z')
- {
- // we accept this as a variation
- if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
- {
- throw new IllegalArgumentException("time needs to be in format YYMMDDHHMMSSZ");
- }
- }
-
- this.time = Strings.toByteArray(time);
+ super(date);
}
- /**
- * base constructor from a java.util.date object
- */
- public DERUTCTime(
- Date time)
+ public DERUTCTime(String time)
{
- this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
- }
-
- DERUTCTime(
- byte[] time)
- {
- this.time = time;
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- */
- public Date getDate()
- {
- return DateFormatter.adjustedFromUTCDateString(time);
- }
-
- /**
- * return the time as an adjusted date
- * in the range of 1950 - 2049.
- *
- * @return a date in the range of 1950 to 2049.
- */
- public Date getAdjustedDate()
- {
- return DateFormatter.adjustedFromUTCDateString(time);
- }
-
- /**
- * return the time - always in the form of
- * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- *
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- *
- * Note: In some cases, due to the local date processing, this
- * may lead to unexpected results. If you want to stick the normal
- * convention of 1950 to 2049 use the getAdjustedTime() method.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
- {
- if (stime.length() == 11)
- {
- return stime.substring(0, 10) + "00GMT+00:00";
- }
- else
- {
- return stime.substring(0, 12) + "GMT+00:00";
- }
- }
- else
- {
- int index = stime.indexOf('-');
- if (index < 0)
- {
- index = stime.indexOf('+');
- }
- String d = stime;
-
- if (index == stime.length() - 3)
- {
- d += "00";
- }
-
- if (index == 10)
- {
- return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
- }
- else
- {
- return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
- }
- }
- }
-
- /**
- * return a time string as an adjusted date with a 4 digit year. This goes
- * in the range of 1950 - 2049.
- */
- public String getAdjustedTime()
- {
- String d = this.getTime();
-
- if (d.charAt(0) < '5')
- {
- return "20" + d;
- }
- else
- {
- return "19" + d;
- }
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return Strings.fromByteArray(time);
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.write(BERTags.UTC_TIME);
-
- int length = time.length;
-
- out.writeLength(length);
-
- for (int i = 0; i != length; i++)
- {
- out.write((byte)time[i]);
- }
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERUTCTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((DERUTCTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
- }
-
- public String toString()
- {
- return Strings.fromByteArray(time);
+ super(time);
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java
index f9ddfc2ed..5609cb720 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/cms/Time.java
@@ -7,8 +7,8 @@ import org.spongycastle.asn1.ASN1Choice;
import org.spongycastle.asn1.ASN1Object;
import org.spongycastle.asn1.ASN1Primitive;
import org.spongycastle.asn1.ASN1TaggedObject;
-import org.spongycastle.asn1.DERGeneralizedTime;
-import org.spongycastle.asn1.DERUTCTime;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1UTCTime;
public class Time
extends ASN1Object
@@ -26,8 +26,8 @@ public class Time
public Time(
ASN1Primitive time)
{
- if (!(time instanceof DERUTCTime)
- && !(time instanceof DERGeneralizedTime))
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
@@ -51,11 +51,11 @@ public class Time
if (year < 1950 || year > 2049)
{
- time = new DERGeneralizedTime(date);
+ time = new ASN1GeneralizedTime(date);
}
else
{
- time = new DERUTCTime(date);
+ time = new ASN1UTCTime(date);
}
}
@@ -66,13 +66,13 @@ public class Time
{
return (Time)obj;
}
- else if (obj instanceof DERUTCTime)
+ else if (obj instanceof ASN1UTCTime)
{
- return new Time((DERUTCTime)obj);
+ return new Time((ASN1UTCTime)obj);
}
- else if (obj instanceof DERGeneralizedTime)
+ else if (obj instanceof ASN1GeneralizedTime)
{
- return new Time((DERGeneralizedTime)obj);
+ return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
@@ -80,25 +80,25 @@ public class Time
public String getTime()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedTime();
+ return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
- return ((DERGeneralizedTime)time).getTime();
+ return ((ASN1GeneralizedTime)time).getTime();
}
}
public Date getDate()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedDate();
+ return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
- return ((DERGeneralizedTime)time).getDate();
+ return ((ASN1GeneralizedTime)time).getDate();
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java
index 0fe22ddc7..f388be8de 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/x509/Time.java
@@ -7,8 +7,8 @@ import org.spongycastle.asn1.ASN1Choice;
import org.spongycastle.asn1.ASN1Object;
import org.spongycastle.asn1.ASN1Primitive;
import org.spongycastle.asn1.ASN1TaggedObject;
-import org.spongycastle.asn1.DERGeneralizedTime;
-import org.spongycastle.asn1.DERUTCTime;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1UTCTime;
public class Time
extends ASN1Object
@@ -26,8 +26,8 @@ public class Time
public Time(
ASN1Primitive time)
{
- if (!(time instanceof DERUTCTime)
- && !(time instanceof DERGeneralizedTime))
+ if (!(time instanceof ASN1UTCTime)
+ && !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
@@ -51,11 +51,11 @@ public class Time
if (year < 1950 || year > 2049)
{
- time = new DERGeneralizedTime(date);
+ time = new ASN1GeneralizedTime(date);
}
else
{
- time = new DERUTCTime(date);
+ time = new ASN1UTCTime(date);
}
}
@@ -66,13 +66,13 @@ public class Time
{
return (Time)obj;
}
- else if (obj instanceof DERUTCTime)
+ else if (obj instanceof ASN1UTCTime)
{
- return new Time((DERUTCTime)obj);
+ return new Time((ASN1UTCTime)obj);
}
- else if (obj instanceof DERGeneralizedTime)
+ else if (obj instanceof ASN1GeneralizedTime)
{
- return new Time((DERGeneralizedTime)obj);
+ return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
@@ -80,25 +80,25 @@ public class Time
public String getTime()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedTime();
+ return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
- return ((DERGeneralizedTime)time).getTime();
+ return ((ASN1GeneralizedTime)time).getTime();
}
}
public Date getDate()
{
- if (time instanceof DERUTCTime)
+ if (time instanceof ASN1UTCTime)
{
- return ((DERUTCTime)time).getAdjustedDate();
+ return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
- return ((DERGeneralizedTime)time).getDate();
+ return ((ASN1GeneralizedTime)time).getDate();
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java
index 3149a1f37..7af31f36e 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/encodings/PKCS1Encoding.java
@@ -1,13 +1,13 @@
package org.spongycastle.crypto.encodings;
+import java.security.SecureRandom;
+
import org.spongycastle.crypto.AsymmetricBlockCipher;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.InvalidCipherTextException;
import org.spongycastle.crypto.params.AsymmetricKeyParameter;
import org.spongycastle.crypto.params.ParametersWithRandom;
-import java.security.SecureRandom;
-
/**
* this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
* depends on your application - see PKCS1 Version 2 for details.
@@ -32,6 +32,8 @@ public class PKCS1Encoding
private boolean forEncryption;
private boolean forPrivateKey;
private boolean useStrictLength;
+ private int pLen = -1;
+ private byte[] fallback = null;
/**
* Basic constructor.
@@ -44,11 +46,48 @@ public class PKCS1Encoding
this.useStrictLength = useStrict();
}
+ /**
+ * Constructor for decryption with a fixed plaintext length.
+ *
+ * @param cipher The cipher to use for cryptographic operation.
+ * @param pLen Length of the expected plaintext.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ int pLen)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.pLen = pLen;
+ }
+
+ /**
+ * Constructor for decryption with a fixed plaintext length and a fallback
+ * value that is returned, if the padding is incorrect.
+ *
+ * @param cipher
+ * The cipher to use for cryptographic operation.
+ * @param fallback
+ * The fallback value, we don't to a arraycopy here.
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher,
+ byte[] fallback)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ this.fallback = fallback;
+ this.pLen = fallback.length;
+ }
+
+
+
//
// for J2ME compatibility
//
private boolean useStrict()
{
+ // required if security manager has been installed.
String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
return strict == null || strict.equals("true");
@@ -174,6 +213,121 @@ public class PKCS1Encoding
return engine.processBlock(block, 0, block.length);
}
+
+ /**
+ * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+ * for encryption.
+ *
+ * @param encoded The Plaintext.
+ * @param pLen Expected length of the plaintext.
+ * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+ */
+ private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
+ int correct = 0;
+ /*
+ * Check if the first two bytes are 0 2
+ */
+ correct |= (encoded[0] ^ 2);
+
+ /*
+ * Now the padding check, check for no 0 byte in the padding
+ */
+ int plen = encoded.length - (
+ pLen /* Lenght of the PMS */
+ + 1 /* Final 0-byte before PMS */
+ );
+
+ for (int i = 1; i < plen; i++) {
+ int tmp = encoded[i];
+ tmp |= tmp >> 1;
+ tmp |= tmp >> 2;
+ tmp |= tmp >> 4;
+ correct |= (tmp & 1) - 1;
+ }
+
+ /*
+ * Make sure the padding ends with a 0 byte.
+ */
+ correct |= encoded[encoded.length - (pLen +1)];
+
+ /*
+ * Return 0 or 1, depending on the result.
+ */
+ correct |= correct >> 1;
+ correct |= correct >> 2;
+ correct |= correct >> 4;
+ return ~((correct & 1) - 1);
+ }
+
+
+ /**
+ * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+ *
+ * @param in The encrypted block.
+ * @param inOff Offset in the encrypted block.
+ * @param inLen Length of the encrypted block.
+ * //@param pLen Length of the desired output.
+ * @return The plaintext without padding, or a random value if the padding was incorrect.
+ *
+ * @throws InvalidCipherTextException
+ */
+ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (!forPrivateKey)
+ {
+ throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ byte[] random = null;
+ if (this.fallback == null)
+ {
+ random = new byte[this.pLen];
+ this.random.nextBytes(random);
+ }
+ else
+ {
+ random = fallback;
+ }
+
+ /*
+ * TODO: This is a potential dangerous side channel. However, you can
+ * fix this by changing the RSA engine in a way, that it will always
+ * return blocks of the same length and prepend them with 0 bytes if
+ * needed.
+ */
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ /*
+ * TODO: Potential side channel. Fix it by making the engine always
+ * return blocks of the correct length.
+ */
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ /*
+ * Check the padding.
+ */
+ int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
+
+ /*
+ * Now, to a constant time constant memory copy of the decrypted value
+ * or the random value, depending on the validity of the padding.
+ */
+ byte[] result = new byte[this.pLen];
+ for (int i = 0; i < this.pLen; i++)
+ {
+ result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
+ }
+
+ return result;
+ }
/**
* @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
@@ -184,7 +338,15 @@ public class PKCS1Encoding
int inLen)
throws InvalidCipherTextException
{
- byte[] block = engine.processBlock(in, inOff, inLen);
+ /*
+ * If the length of the expected plaintext is known, we use a constant-time decryption.
+ * If the decryption fails, we return a random value.
+ */
+ if (this.pLen != -1) {
+ return this.decodeBlockOrRandom(in, inOff, inLen);
+ }
+
+ byte[] block = engine.processBlock(in, inOff, inLen);
if (block.length < getOutputBlockSize())
{
@@ -192,10 +354,20 @@ public class PKCS1Encoding
}
byte type = block[0];
-
- if (type != 1 && type != 2)
+
+ if (forPrivateKey)
{
- throw new InvalidCipherTextException("unknown block type");
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
+ {
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
}
if (useStrictLength && block.length != engine.getOutputBlockSize())
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java
index c66d76dc7..ea68af90f 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/crypto/tls/OCSPStatusRequest.java
@@ -90,11 +90,11 @@ public class OCSPStatusRequest
}
/**
- * Parse a {@link OCSPStatusRequest} from an {@link InputStream}.
+ * Parse an {@link OCSPStatusRequest} from an {@link InputStream}.
*
* @param input
* the {@link InputStream} to parse from.
- * @return a {@link OCSPStatusRequest} object.
+ * @return an {@link OCSPStatusRequest} object.
* @throws IOException
*/
public static OCSPStatusRequest parse(InputStream input) throws IOException
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java
index 70117db78..0f626d5c1 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/math/ec/LongArray.java
@@ -371,6 +371,23 @@ class LongArray
}
}
+ public boolean isOne()
+ {
+ long[] a = m_ints;
+ if (a[0] != 1L)
+ {
+ return false;
+ }
+ for (int i = 1; i < a.length; ++i)
+ {
+ if (a[i] != 0L)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
public boolean isZero()
{
long[] a = m_ints;
@@ -822,12 +839,12 @@ class LongArray
add(c, cOff, b, 0, bLen);
}
int k = 1;
- while ((a >>>= 1) != 0)
+ while ((a >>>= 1) != 0L)
{
if ((a & 1L) != 0L)
{
long carry = addShiftedUp(c, cOff, b, 0, bLen, k);
- if (carry != 0)
+ if (carry != 0L)
{
c[cOff + bLen] ^= carry;
}
@@ -871,8 +888,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -880,13 +897,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
/*
@@ -1003,8 +1020,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -1012,13 +1029,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
/*
@@ -1077,7 +1094,8 @@ class LongArray
aVal >>>= 4;
int v = (int)aVal & MASK;
addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
- if ((aVal >>>= 4) == 0L)
+ aVal >>>= 4;
+ if (aVal == 0L)
{
break;
}
@@ -1085,10 +1103,12 @@ class LongArray
}
}
- int cOff = c.length;
- while ((cOff -= cLen) != 0)
{
- addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
}
/*
@@ -1132,8 +1152,8 @@ class LongArray
if (aLen == 1)
{
- long a = A.m_ints[0];
- if (a == 1L)
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
{
return B;
}
@@ -1141,13 +1161,13 @@ class LongArray
/*
* Fast path for small A, with performance dependent only on the number of set bits
*/
- long[] c = new long[cLen];
- multiplyWord(a, B.m_ints, bLen, c, 0);
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
/*
* Reduce the raw answer against the reduction coefficients
*/
- return reduceResult(c, 0, cLen, m, ks);
+ return reduceResult(c0, 0, cLen, m, ks);
}
// NOTE: This works, but is slower than width 4 processing
@@ -1314,6 +1334,158 @@ class LongArray
return reduceResult(c, ci[1], cLen, m, ks);
}
+ public LongArray modReduce(int m, int[] ks)
+ {
+ long[] buf = Arrays.clone(m_ints);
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ return new LongArray(buf, 0, rLen);
+ }
+
+ public LongArray multiply(LongArray other, int m, int[] ks)
+ {
+ /*
+ * Find out the degree of each argument and handle the zero cases
+ */
+ int aDeg = degree();
+ if (aDeg == 0)
+ {
+ return this;
+ }
+ int bDeg = other.degree();
+ if (bDeg == 0)
+ {
+ return other;
+ }
+
+ /*
+ * Swap if necessary so that A is the smaller argument
+ */
+ LongArray A = this, B = other;
+ if (aDeg > bDeg)
+ {
+ A = other; B = this;
+ int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+ }
+
+ /*
+ * Establish the word lengths of the arguments and result
+ */
+ int aLen = (aDeg + 63) >>> 6;
+ int bLen = (bDeg + 63) >>> 6;
+ int cLen = (aDeg + bDeg + 62) >>> 6;
+
+ if (aLen == 1)
+ {
+ long a0 = A.m_ints[0];
+ if (a0 == 1L)
+ {
+ return B;
+ }
+
+ /*
+ * Fast path for small A, with performance dependent only on the number of set bits
+ */
+ long[] c0 = new long[cLen];
+ multiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+ /*
+ * Reduce the raw answer against the reduction coefficients
+ */
+// return reduceResult(c0, 0, cLen, m, ks);
+ return new LongArray(c0, 0, cLen);
+ }
+
+ /*
+ * Determine if B will get bigger during shifting
+ */
+ int bMax = (bDeg + 7 + 63) >>> 6;
+
+ /*
+ * Lookup table for the offset of each B in the tables
+ */
+ int[] ti = new int[16];
+
+ /*
+ * Precompute table of all 4-bit products of B
+ */
+ long[] T0 = new long[bMax << 4];
+ int tOff = bMax;
+ ti[1] = tOff;
+ System.arraycopy(B.m_ints, 0, T0, tOff, bLen);
+ for (int i = 2; i < 16; ++i)
+ {
+ ti[i] = (tOff += bMax);
+ if ((i & 1) == 0)
+ {
+ shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1);
+ }
+ else
+ {
+ add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+ }
+ }
+
+ /*
+ * Second table with all 4-bit products of B shifted 4 bits
+ */
+ long[] T1 = new long[T0.length];
+ shiftUp(T0, 0, T1, 0, T0.length, 4);
+// shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+ long[] a = A.m_ints;
+ long[] c = new long[cLen << 3];
+
+ int MASK = 0xF;
+
+ /*
+ * Lopez-Dahab (Modified) algorithm
+ */
+
+ for (int aPos = 0; aPos < aLen; ++aPos)
+ {
+ long aVal = a[aPos];
+ int cOff = aPos;
+ for (;;)
+ {
+ int u = (int)aVal & MASK;
+ aVal >>>= 4;
+ int v = (int)aVal & MASK;
+ addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+ aVal >>>= 4;
+ if (aVal == 0L)
+ {
+ break;
+ }
+ cOff += cLen;
+ }
+ }
+
+ {
+ int cOff = c.length;
+ while ((cOff -= cLen) != 0)
+ {
+ addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+ }
+ }
+
+ /*
+ * Finally the raw answer is collected, reduce it against the reduction coefficients
+ */
+// return reduceResult(c, 0, cLen, m, ks);
+ return new LongArray(c, 0, cLen);
+ }
+
+ public void reduce(int m, int[] ks)
+ {
+ long[] buf = m_ints;
+ int rLen = reduceInPlace(buf, 0, buf.length, m, ks);
+ if (rLen < buf.length)
+ {
+ m_ints = new long[rLen];
+ System.arraycopy(buf, 0, m_ints, 0, rLen);
+ }
+ }
+
private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks)
{
int rLen = reduceInPlace(buf, off, len, m, ks);
@@ -1405,13 +1577,13 @@ class LongArray
private static void reduceBit(long[] buf, int off, int bit, int m, int[] ks)
{
flipBit(buf, off, bit);
- int base = bit - m;
+ int n = bit - m;
int j = ks.length;
while (--j >= 0)
{
- flipBit(buf, off, ks[j] + base);
+ flipBit(buf, off, ks[j] + n);
}
- flipBit(buf, off, base);
+ flipBit(buf, off, n);
}
private static void reduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
@@ -1428,12 +1600,14 @@ class LongArray
}
}
- int partial = toBit & 0x3F;
- long word = buf[off + toPos] >>> partial;
- if (word != 0)
{
- buf[off + toPos] ^= word << partial;
- reduceWord(buf, off, toBit, word, m, ks);
+ int partial = toBit & 0x3F;
+ long word = buf[off + toPos] >>> partial;
+ if (word != 0)
+ {
+ buf[off + toPos] ^= word << partial;
+ reduceWord(buf, off, toBit, word, m, ks);
+ }
}
}
@@ -1502,37 +1676,59 @@ class LongArray
return new LongArray(r, 0, reduceInPlace(r, 0, r.length, m, ks));
}
-// private LongArray modSquareN(int n, int m, int[] ks)
-// {
-// int len = getUsedLength();
-// if (len == 0)
-// {
-// return this;
-// }
-//
-// int mLen = (m + 63) >>> 6;
-// long[] r = new long[mLen << 1];
-// System.arraycopy(m_ints, 0, r, 0, len);
-//
-// while (--n >= 0)
-// {
-// squareInPlace(r, len, m, ks);
-// len = reduceInPlace(r, 0, r.length, m, ks);
-// }
-//
-// return new LongArray(r, 0, len);
-// }
-//
-// private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
-// {
-// int pos = xLen << 1;
-// while (--xLen >= 0)
-// {
-// long xVal = x[xLen];
-// x[--pos] = interleave2_32to64((int)(xVal >>> 32));
-// x[--pos] = interleave2_32to64((int)xVal);
-// }
-// }
+ public LongArray modSquareN(int n, int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int mLen = (m + 63) >>> 6;
+ long[] r = new long[mLen << 1];
+ System.arraycopy(m_ints, 0, r, 0, len);
+
+ while (--n >= 0)
+ {
+ squareInPlace(r, len, m, ks);
+ len = reduceInPlace(r, 0, r.length, m, ks);
+ }
+
+ return new LongArray(r, 0, len);
+ }
+
+ public LongArray square(int m, int[] ks)
+ {
+ int len = getUsedLength();
+ if (len == 0)
+ {
+ return this;
+ }
+
+ int _2len = len << 1;
+ long[] r = new long[_2len];
+
+ int pos = 0;
+ while (pos < _2len)
+ {
+ long mi = m_ints[pos >>> 1];
+ r[pos++] = interleave2_32to64((int)mi);
+ r[pos++] = interleave2_32to64((int)(mi >>> 32));
+ }
+
+ return new LongArray(r, 0, r.length);
+ }
+
+ private static void squareInPlace(long[] x, int xLen, int m, int[] ks)
+ {
+ int pos = xLen << 1;
+ while (--xLen >= 0)
+ {
+ long xVal = x[xLen];
+ x[--pos] = interleave2_32to64((int)(xVal >>> 32));
+ x[--pos] = interleave2_32to64((int)xVal);
+ }
+ }
private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
{
@@ -1856,6 +2052,10 @@ class LongArray
* Output: a(z)^(-1) mod f(z)
*/
int uzDegree = degree();
+ if (uzDegree == 0)
+ {
+ throw new IllegalStateException();
+ }
if (uzDegree == 1)
{
return this;
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Integers.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Integers.java
index 3ac592d3c..bf6b5e345 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Integers.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Integers.java
@@ -2,6 +2,16 @@ package org.spongycastle.util;
public class Integers
{
+ public static int rotateLeft(int i, int distance)
+ {
+ return (i << distance) ^ (i >>> -distance);
+ }
+
+ public static int rotateRight(int i, int distance)
+ {
+ return (i >>> distance) ^ (i << -distance);
+ }
+
public static Integer valueOf(int value)
{
return new Integer(value);
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Times.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Times.java
new file mode 100644
index 000000000..f88b5395c
--- /dev/null
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/util/Times.java
@@ -0,0 +1,11 @@
+package org.spongycastle.util;
+
+public final class Times
+{
+ private static long NANOS_PER_MILLI = 1000000L;
+
+ public static long nanoTime()
+ {
+ return NANOS_PER_MILLI * System.currentTimeMillis();
+ }
+}
diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/LICENSE.java b/extern/spongycastle/core/src/main/java/org/spongycastle/LICENSE.java
index 835294251..9733cc574 100644
--- a/extern/spongycastle/core/src/main/java/org/spongycastle/LICENSE.java
+++ b/extern/spongycastle/core/src/main/java/org/spongycastle/LICENSE.java
@@ -3,7 +3,7 @@ package org.spongycastle;
/**
* The Bouncy Castle License
*
- * Copyright (c) 2000-2013 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+ * Copyright (c) 2000-2014 The Legion Of The Bouncy Castle Inc. (http://www.bouncycastle.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
@@ -24,7 +24,7 @@ package org.spongycastle;
public class LICENSE
{
public static String licenseText =
- "Copyright (c) 2000-2013 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) "
+ "Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) "
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software "
diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java
index 5a48fbf5a..4f643349d 100644
--- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java
+++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1ApplicationSpecificParser.java
@@ -2,9 +2,18 @@ package org.spongycastle.asn1;
import java.io.IOException;
+/**
+ * Interface to parse ASN.1 application specific objects.
+ */
public interface ASN1ApplicationSpecificParser
extends ASN1Encodable, InMemoryRepresentable
{
+ /**
+ * Read the next object in the parser.
+ *
+ * @return an ASN1Encodable
+ * @throws IOException on a parsing or decoding error.
+ */
ASN1Encodable readObject()
throws IOException;
}
diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java
index 9a9c3a084..47091bd97 100644
--- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java
+++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Boolean.java
@@ -1,15 +1,204 @@
package org.spongycastle.asn1;
+import java.io.IOException;
+
+import org.spongycastle.util.Arrays;
+
+/**
+ * Public facade of ASN.1 Boolean data.
+ *
+ * Use following to place a new instance of ASN.1 Boolean in your dataset:
+ *
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.charAt(stime.length() - 1) == 'Z')
+ {
+ return stime.substring(0, stime.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = stime.length() - 5;
+ char sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos, signPos + 3)
+ + ":"
+ + stime.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = stime.length() - 3;
+ sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return stime + calculateGMTOffset();
+ }
+
+ private String calculateGMTOffset()
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+// try
+// {
+// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
+// {
+// hours += sign.equals("+") ? 1 : -1;
+// }
+// }
+// catch (ParseException e)
+// {
+// // we'll do our best and ignore daylight savings
+// }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public Date getDate()
+ {
+ return DateFormatter.fromGeneralizedTimeString(time);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ for (int i = 0; i != time.length; i++)
+ {
+ if (time[i] == '.')
+ {
+ if (i == 14)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, time);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1GeneralizedTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java
index d682a182f..271a2cdc0 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/ASN1UTCTime.java
@@ -1,22 +1,259 @@
package org.spongycastle.asn1;
+import java.io.IOException;
import java.util.Date;
+import org.spongycastle.util.Arrays;
+import org.spongycastle.util.Strings;
+
+/**
+ * UTC time object.
+ */
public class ASN1UTCTime
- extends DERUTCTime
+ extends ASN1Primitive
{
- ASN1UTCTime(byte[] bytes)
+ private byte[] time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1UTCTime getInstance(
+ Object obj)
{
- super(bytes);
+ if (obj == null || obj instanceof ASN1UTCTime)
+ {
+ return (ASN1UTCTime)obj;
+ }
+
+ if (obj instanceof ASN1UTCTime)
+ {
+ return new ASN1UTCTime(((ASN1UTCTime)obj).time);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
- public ASN1UTCTime(Date date)
+ /**
+ * return an UTC Time 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 ASN1UTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
{
- super(date);
+ ASN1Object o = obj.getObject();
+
+ if (explicit || o instanceof ASN1UTCTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever gets read from
+ * the input stream... (this is why the input format is different from the getTime()
+ * method output).
+ *
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ *
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- *
- * To read in the time and get a date which is compatible with our local
- * time zone.
- */
- public String getTime()
- {
- String stime = Strings.fromByteArray(time);
-
- //
- // standardise the format.
- //
- if (stime.charAt(stime.length() - 1) == 'Z')
- {
- return stime.substring(0, stime.length() - 1) + "GMT+00:00";
- }
- else
- {
- int signPos = stime.length() - 5;
- char sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos, signPos + 3)
- + ":"
- + stime.substring(signPos + 3);
- }
- else
- {
- signPos = stime.length() - 3;
- sign = stime.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return stime.substring(0, signPos)
- + "GMT"
- + stime.substring(signPos)
- + ":00";
- }
- }
- }
- return stime + calculateGMTOffset();
- }
-
- private String calculateGMTOffset()
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
-// try
-// {
-// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
-// {
-// hours += sign.equals("+") ? 1 : -1;
-// }
-// }
-// catch (ParseException e)
-// {
-// // we'll do our best and ignore daylight savings
-// }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public Date getDate()
- {
- return DateFormatter.fromGeneralizedTimeString(time);
- }
-
- private boolean hasFractionalSeconds()
- {
- for (int i = 0; i != time.length; i++)
- {
- if (time[i] == '.')
- {
- if (i == 14)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- boolean isConstructed()
- {
- return false;
- }
-
- int encodedLength()
- {
- int length = time.length;
-
- return 1 + StreamUtil.calculateBodyLength(length) + length;
- }
-
- void encode(
- ASN1OutputStream out)
- throws IOException
- {
- out.writeEncoded(BERTags.GENERALIZED_TIME, time);
- }
-
- boolean asn1Equals(
- ASN1Primitive o)
- {
- if (!(o instanceof DERGeneralizedTime))
- {
- return false;
- }
-
- return Arrays.areEqual(time, ((DERGeneralizedTime)o).time);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(time);
+ super(time);
}
}
diff --git a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java
index bc0411f76..4b0379b55 100644
--- a/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java
+++ b/extern/spongycastle/core/src/main/j2me/org/spongycastle/asn1/DERUTCTime.java
@@ -1,259 +1,22 @@
package org.spongycastle.asn1;
-import java.io.IOException;
import java.util.Date;
-import org.spongycastle.util.Arrays;
-import org.spongycastle.util.Strings;
-
-/**
- * UTC time object.
- */
public class DERUTCTime
- extends ASN1Primitive
+ extends ASN1UTCTime
{
- private byte[] time;
-
- /**
- * return an UTC Time from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1UTCTime getInstance(
- Object obj)
+ DERUTCTime(byte[] bytes)
{
- if (obj == null || obj instanceof ASN1UTCTime)
- {
- return (ASN1UTCTime)obj;
- }
-
- if (obj instanceof DERUTCTime)
- {
- return new ASN1UTCTime(((DERUTCTime)obj).time);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ super(bytes);
}
- /**
- * return an UTC Time 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 ASN1UTCTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
+ public DERUTCTime(Date date)
{
- ASN1Object o = obj.getObject();
-
- if (explicit || o instanceof ASN1UTCTime)
- {
- return getInstance(o);
- }
- else
- {
- return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
- }
- }
-
- /**
- * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
- * never encoded. When you're creating one of these objects from scratch, that's
- * what you want to use, otherwise we'll try to deal with whatever gets read from
- * the input stream... (this is why the input format is different from the getTime()
- * method output).
- *
- * dateF = new SimpleDateFormat("yyMMddHHmmssz");
- *
- * To read in the time and get a date which is compatible with our local
- * time zone.
- *
+ *
+ *
- * If you use this interface your class should also implement the getInstance - * pattern which takes a tag object and the tagging mode used. + * If you use this interface your class should also implement the getInstance() + * pattern which takes a tag object and the tagging mode used. + *
+ *
X.690
+ *8: Basic encoding rules
+ *8.13 Encoding of a choice value
+ *+ * The encoding of a choice value shall be the same as the encoding of a value of the chosen type. + *
+ * NOTE 1 — The encoding may be primitive or constructed depending on the chosen type. + *+ * */ public interface ASN1Choice { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java index ec7607d5e..60a57e380 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encodable.java @@ -1,6 +1,13 @@ package org.spongycastle.asn1; +/** + * Basic interface to produce serialisers for ASN.1 encodings. + */ public interface ASN1Encodable { + /** + * Return an object, possibly constructed, of ASN.1 primitives + * @return an ASN.1 primitive. + */ ASN1Primitive toASN1Primitive(); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java index 0ef3af173..61984aa48 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1EncodableVector.java @@ -3,19 +3,35 @@ package org.spongycastle.asn1; import java.util.Enumeration; import java.util.Vector; +/** + * Mutable class for building ASN.1 constructed objects. + */ public class ASN1EncodableVector { Vector v = new Vector(); + /** + * Base constructor. + */ public ASN1EncodableVector() { } + /** + * Add an encodable to the vector. + * + * @param obj the encodable to add. + */ public void add(ASN1Encodable obj) { v.addElement(obj); } + /** + * Add the contents of another vector. + * + * @param other the vector to add. + */ public void addAll(ASN1EncodableVector other) { for (Enumeration en = other.v.elements(); en.hasMoreElements();) @@ -24,11 +40,22 @@ public class ASN1EncodableVector } } + /** + * Return the object at position i in this vector. + * + * @param i the index of the object of interest. + * @return the object at position i. + */ public ASN1Encodable get(int i) { return (ASN1Encodable)v.elementAt(i); } + /** + * Return the size of the vector. + * + * @return the object count in the vector. + */ public int size() { return v.size(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java index 7f7178d4c..683e752df 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Encoding.java @@ -1,8 +1,22 @@ package org.spongycastle.asn1; +/** + * Supported encoding formats. + */ public interface ASN1Encoding { + /** + * DER - distinguished encoding rules. + */ static final String DER = "DER"; + + /** + * DL - definite length encoding. + */ static final String DL = "DL"; + + /** + * BER - basic encoding rules. + */ static final String BER = "BER"; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java index 02d1a308c..bb9f15ebe 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Enumerated.java @@ -1,22 +1,174 @@ package org.spongycastle.asn1; +import java.io.IOException; import java.math.BigInteger; +import org.spongycastle.util.Arrays; + +/** + * Class representing the ASN.1 ENUMERATED type. + */ public class ASN1Enumerated - extends DEREnumerated + extends ASN1Primitive { - ASN1Enumerated(byte[] bytes) + byte[] bytes; + + /** + * return an enumerated from the passed in object + * + * @param obj an ASN1Enumerated or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return an ASN1Enumerated instance, or null. + */ + public static ASN1Enumerated getInstance( + Object obj) { - super(bytes); + if (obj == null || obj instanceof ASN1Enumerated) + { + return (ASN1Enumerated)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (ASN1Enumerated)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } - public ASN1Enumerated(BigInteger value) + /** + * return an Enumerated 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. + * @return an ASN1Enumerated instance, or null. + */ + public static ASN1Enumerated getInstance( + ASN1TaggedObject obj, + boolean explicit) { - super(value); + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof ASN1Enumerated) + { + return getInstance(o); + } + else + { + return fromOctetString(((ASN1OctetString)o).getOctets()); + } } - public ASN1Enumerated(int value) + /** + * Constructor from int. + * + * @param value the value of this enumerated. + */ + public ASN1Enumerated( + int value) { - super(value); + bytes = BigInteger.valueOf(value).toByteArray(); + } + + /** + * Constructor from BigInteger + * + * @param value the value of this enumerated. + */ + public ASN1Enumerated( + BigInteger value) + { + bytes = value.toByteArray(); + } + + /** + * Constructor from encoded BigInteger. + * + * @param bytes the value of this enumerated as an encoded BigInteger (signed). + */ + public ASN1Enumerated( + byte[] bytes) + { + this.bytes = bytes; + } + + public BigInteger getValue() + { + return new BigInteger(bytes); + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.writeEncoded(BERTags.ENUMERATED, bytes); + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1Enumerated)) + { + return false; + } + + ASN1Enumerated other = (ASN1Enumerated)o; + + return Arrays.areEqual(this.bytes, other.bytes); + } + + public int hashCode() + { + return Arrays.hashCode(bytes); + } + + private static ASN1Enumerated[] cache = new ASN1Enumerated[12]; + + static ASN1Enumerated fromOctetString(byte[] enc) + { + if (enc.length > 1) + { + return new ASN1Enumerated(Arrays.clone(enc)); + } + + if (enc.length == 0) + { + throw new IllegalArgumentException("ENUMERATED has zero length"); + } + int value = enc[0] & 0xff; + + if (value >= cache.length) + { + return new ASN1Enumerated(Arrays.clone(enc)); + } + + ASN1Enumerated possibleMatch = cache[value]; + + if (possibleMatch == null) + { + possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc)); + } + + return possibleMatch; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java index d507decd9..c69720a13 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1GeneralizedTime.java @@ -1,22 +1,373 @@ package org.spongycastle.asn1; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Strings; + +/** + * Base class representing the ASN.1 GeneralizedTime type. + *+ * NOTE 2 — The tag used in the identifier octets is the tag of the chosen type, + * as specified in the ASN.1 definition of the choice type. + *
+ * The main difference between these and UTC time is a 4 digit year. + *
+ */ public class ASN1GeneralizedTime - extends DERGeneralizedTime + extends ASN1Primitive { - ASN1GeneralizedTime(byte[] bytes) + private byte[] time; + + /** + * return a generalized time from the passed in object + * + * @param obj an ASN1GeneralizedTime or an object that can be converted into one. + * @return an ASN1GeneralizedTime instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static ASN1GeneralizedTime getInstance( + Object obj) { - super(bytes); + if (obj == null || obj instanceof ASN1GeneralizedTime) + { + return (ASN1GeneralizedTime)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (ASN1GeneralizedTime)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } - public ASN1GeneralizedTime(Date time) + /** + * return a Generalized Time object 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. + * @return an ASN1GeneralizedTime instance. + * @throws IllegalArgumentException if the tagged object cannot + * be converted. + */ + public static ASN1GeneralizedTime getInstance( + ASN1TaggedObject obj, + boolean explicit) { - super(time); + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof ASN1GeneralizedTime) + { + return getInstance(o); + } + else + { + return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets()); + } } - public ASN1GeneralizedTime(String time) + /** + * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z + * for local time, or Z+-HHMM on the end, for difference between local + * time and UTC time. The fractional second amount f must consist of at + * least one number with trailing zeroes removed. + * + * @param time the time string. + * @throws IllegalArgumentException if String is an illegal format. + */ + public ASN1GeneralizedTime( + String time) { - super(time); + this.time = Strings.toByteArray(time); + try + { + this.getDate(); + } + catch (ParseException e) + { + throw new IllegalArgumentException("invalid date string: " + e.getMessage()); + } + } + + /** + * Base constructor from a java.util.date object + * + * @param time a date object representing the time of interest. + */ + public ASN1GeneralizedTime( + Date time) + { + SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); + + dateF.setTimeZone(new SimpleTimeZone(0, "Z")); + + this.time = Strings.toByteArray(dateF.format(time)); + } + + /** + * Base constructor from a java.util.date and Locale - you may need to use this if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. + * + * @param time a date object representing the time of interest. + * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value. + */ + public ASN1GeneralizedTime( + Date time, + Locale locale) + { + SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", locale); + + dateF.setTimeZone(new SimpleTimeZone(0, "Z")); + + this.time = Strings.toByteArray(dateF.format(time)); + } + + ASN1GeneralizedTime( + byte[] bytes) + { + this.time = bytes; + } + + /** + * Return the time. + * + * @return The time string as it appeared in the encoded object. + */ + public String getTimeString() + { + return Strings.fromByteArray(time); + } + + /** + * return the time - always in the form of + * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm). + * + * Normally in a certificate we would expect "Z" rather than "GMT", + * however adding the "GMT" means we can just use: + *+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); + *+ * To read in the time and get a date which is compatible with our local + * time zone. + */ + public String getTime() + { + String stime = Strings.fromByteArray(time); + + // + // standardise the format. + // + if (stime.charAt(stime.length() - 1) == 'Z') + { + return stime.substring(0, stime.length() - 1) + "GMT+00:00"; + } + else + { + int signPos = stime.length() - 5; + char sign = stime.charAt(signPos); + if (sign == '-' || sign == '+') + { + return stime.substring(0, signPos) + + "GMT" + + stime.substring(signPos, signPos + 3) + + ":" + + stime.substring(signPos + 3); + } + else + { + signPos = stime.length() - 3; + sign = stime.charAt(signPos); + if (sign == '-' || sign == '+') + { + return stime.substring(0, signPos) + + "GMT" + + stime.substring(signPos) + + ":00"; + } + } + } + return stime + calculateGMTOffset(); + } + + private String calculateGMTOffset() + { + String sign = "+"; + TimeZone timeZone = TimeZone.getDefault(); + int offset = timeZone.getRawOffset(); + if (offset < 0) + { + sign = "-"; + offset = -offset; + } + int hours = offset / (60 * 60 * 1000); + int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000); + + try + { + if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate())) + { + hours += sign.equals("+") ? 1 : -1; + } + } + catch (ParseException e) + { + // we'll do our best and ignore daylight savings + } + + return "GMT" + sign + convert(hours) + ":" + convert(minutes); + } + + private String convert(int time) + { + if (time < 10) + { + return "0" + time; + } + + return Integer.toString(time); + } + + public Date getDate() + throws ParseException + { + SimpleDateFormat dateF; + String stime = Strings.fromByteArray(time); + String d = stime; + + if (stime.endsWith("Z")) + { + if (hasFractionalSeconds()) + { + dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'"); + } + else + { + dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); + } + + dateF.setTimeZone(new SimpleTimeZone(0, "Z")); + } + else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0) + { + d = this.getTime(); + if (hasFractionalSeconds()) + { + dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz"); + } + else + { + dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); + } + + dateF.setTimeZone(new SimpleTimeZone(0, "Z")); + } + else + { + if (hasFractionalSeconds()) + { + dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + } + else + { + dateF = new SimpleDateFormat("yyyyMMddHHmmss"); + } + + dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); + } + + if (hasFractionalSeconds()) + { + // java misinterprets extra digits as being milliseconds... + String frac = d.substring(14); + int index; + for (index = 1; index < frac.length(); index++) + { + char ch = frac.charAt(index); + if (!('0' <= ch && ch <= '9')) + { + break; + } + } + + if (index - 1 > 3) + { + frac = frac.substring(0, 4) + frac.substring(index); + d = d.substring(0, 14) + frac; + } + else if (index - 1 == 1) + { + frac = frac.substring(0, index) + "00" + frac.substring(index); + d = d.substring(0, 14) + frac; + } + else if (index - 1 == 2) + { + frac = frac.substring(0, index) + "0" + frac.substring(index); + d = d.substring(0, 14) + frac; + } + } + + return dateF.parse(d); + } + + private boolean hasFractionalSeconds() + { + for (int i = 0; i != time.length; i++) + { + if (time[i] == '.') + { + if (i == 14) + { + return true; + } + } + } + return false; + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + int length = time.length; + + return 1 + StreamUtil.calculateBodyLength(length) + length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.writeEncoded(BERTags.GENERALIZED_TIME, time); + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1GeneralizedTime)) + { + return false; + } + + return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time); + } + + public int hashCode() + { + return Arrays.hashCode(time); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java index 19166659c..71eaf4339 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1InputStream.java @@ -124,6 +124,12 @@ public class ASN1InputStream /** * build an object given its tag and the number of bytes to construct it from. + * + * @param tag the full tag details. + * @param tagNo the tagNo defined. + * @param length the length of the object. + * @return the resulting primitive. + * @throws java.io.IOException on processing exception. */ protected ASN1Primitive buildObject( int tag, @@ -438,7 +444,7 @@ public class ASN1InputStream case IA5_STRING: return new DERIA5String(defIn.toByteArray()); case INTEGER: - return new ASN1Integer(defIn.toByteArray()); + return new ASN1Integer(defIn.toByteArray(), false); case NULL: return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?) case NUMERIC_STRING: diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java index d6820c345..1b852176b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Integer.java @@ -1,22 +1,157 @@ package org.spongycastle.asn1; +import java.io.IOException; import java.math.BigInteger; +import org.spongycastle.util.Arrays; + +/** + * Class representing the ASN.1 INTEGER type. + */ public class ASN1Integer - extends DERInteger + extends ASN1Primitive { - ASN1Integer(byte[] bytes) + byte[] bytes; + + /** + * return an integer from the passed in object + * + * @param obj an ASN1Integer or an object that can be converted into one. + * @throws IllegalArgumentException if the object cannot be converted. + * @return an ASN1Integer instance. + */ + public static ASN1Integer getInstance( + Object obj) { - super(bytes); + if (obj == null || obj instanceof ASN1Integer) + { + return (ASN1Integer)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (ASN1Integer)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } - public ASN1Integer(BigInteger value) + /** + * return an Integer 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. + * @throws IllegalArgumentException if the tagged object cannot + * be converted. + * @return an ASN1Integer instance. + */ + public static ASN1Integer getInstance( + ASN1TaggedObject obj, + boolean explicit) { - super(value); + ASN1Primitive o = obj.getObject(); + + if (explicit || o instanceof ASN1Integer) + { + return getInstance(o); + } + else + { + return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets()); + } } - public ASN1Integer(long value) + public ASN1Integer( + long value) { - super(value); + bytes = BigInteger.valueOf(value).toByteArray(); } + + public ASN1Integer( + BigInteger value) + { + bytes = value.toByteArray(); + } + + public ASN1Integer( + byte[] bytes) + { + this(bytes, true); + } + + ASN1Integer(byte[] bytes, boolean clone) + { + this.bytes = (clone) ? Arrays.clone(bytes) : bytes; + } + + public BigInteger getValue() + { + return new BigInteger(bytes); + } + + /** + * in some cases positive values get crammed into a space, + * that's not quite big enough... + * @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned. + */ + public BigInteger getPositiveValue() + { + return new BigInteger(1, bytes); + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.writeEncoded(BERTags.INTEGER, bytes); + } + + public int hashCode() + { + int value = 0; + + for (int i = 0; i != bytes.length; i++) + { + value ^= (bytes[i] & 0xff) << (i % 4); + } + + return value; + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1Integer)) + { + return false; + } + + ASN1Integer other = (ASN1Integer)o; + + return Arrays.areEqual(bytes, other.bytes); + } + + public String toString() + { + return getValue().toString(); + } + } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Null.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Null.java index 647060c1f..f1bd726a1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Null.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Null.java @@ -3,18 +3,26 @@ package org.spongycastle.asn1; import java.io.IOException; /** - * A NULL object. + * A NULL object - use DERNull.INSTANCE for populating structures. */ public abstract class ASN1Null extends ASN1Primitive { /** - * @deprecated use DERNull.INSTANCE + * Return an instance of ASN.1 NULL from the passed in object. + *
+ * Accepted inputs: + *
+ * This supports BER, and DER forms of the data. + *
+ * DER form is always primitive single OCTET STRING, while + * BER support includes the constructed forms. + *
+ *X.690
+ *8: Basic encoding rules
+ *8.7 Encoding of an octetstring value
+ *+ * 8.7.1 The encoding of an octetstring value shall be + * either primitive or constructed at the option of the sender. + *
+ * NOTE — Where it is necessary to transfer part of an octet string + * before the entire OCTET STRING is available, the constructed encoding + * is used. + *+ *
+ * 8.7.2 The primitive encoding contains zero, + * one or more contents octets equal in value to the octets + * in the data value, in the order they appear in the data value, + * and with the most significant bit of an octet of the data value + * aligned with the most significant bit of an octet of the contents octets. + *
+ *+ * 8.7.3 The contents octets for the constructed encoding shall consist + * of zero, one, or more encodings. + *
+ * NOTE — Each such encoding includes identifier, length, and contents octets, + * and may include end-of-contents octets if it is constructed. + *+ * + *
+ * 8.7.3.1 To encode an octetstring value in this way, + * it is segmented. Each segment shall consist of a series of + * consecutive octets of the value. There shall be no significance + * placed on the segment boundaries. + *
+ * NOTE — A segment may be of size zero, i.e. contain no octets. + *+ * + *
+ * 8.7.3.2 Each encoding in the contents octets shall represent + * a segment of the overall octetstring, the encoding arising from + * a recursive application of this subclause. + * In this recursive application, each segment is treated as if it were + * a octetstring value. The encodings of the segments shall appear in the contents + * octets in the order in which their octets appear in the overall value. + *
+ * NOTE 1 — As a consequence of this recursion, + * each encoding in the contents octets may itself + * be primitive or constructed. + * However, such encodings will usually be primitive. + *+ * + *+ * NOTE 2 — In particular, the tags in the contents octets are always universal class, number 4. + *
9: Canonical encoding rules
+ *9.1 Length forms
+ *+ * If the encoding is constructed, it shall employ the indefinite length form. + * If the encoding is primitive, it shall include the fewest length octets necessary. + * [Contrast with 8.1.3.2 b).] + *
+ *9.2 String encoding forms
+ *+ * BIT STRING, OCTET STRING,and restricted character string + * values shall be encoded with a primitive encoding if they would + * require no more than 1000 contents octets, and as a constructed + * encoding otherwise. The string fragments contained in + * the constructed encoding shall be encoded with a primitive encoding. + * The encoding of each fragment, except possibly + * the last, shall have 1000 contents octets. (Contrast with 8.21.6.) + *
+ * 10: Distinguished encoding rules + *+ * 10.1 Length forms + * The definite form of length encoding shall be used, + * encoded in the minimum number of octets. + * [Contrast with 8.1.3.2 b).] + *
+ * 10.2 String encoding forms + * For BIT STRING, OCTET STRING and restricted character string types, + * the constructed form of encoding shall not be used. + * (Contrast with 8.21.6.) + *
+ */ public abstract class ASN1OctetString extends ASN1Primitive implements ASN1OctetStringParser @@ -88,16 +178,31 @@ public abstract class ASN1OctetString this.string = string; } + /** + * Return the content of the OCTET STRING as an InputStream. + * + * @return an InputStream representing the OCTET STRING's content. + */ public InputStream getOctetStream() { return new ByteArrayInputStream(string); } + /** + * Return the parser associated with this object. + * + * @return a parser based on this OCTET STRING + */ public ASN1OctetStringParser parser() { return this; } + /** + * Return the content of the OCTET STRING as a byte array. + * + * @return the byte[] representing the OCTET STRING's content. + */ public byte[] getOctets() { return string; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java index 6b51608ec..f268b17f5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1OctetStringParser.java @@ -2,8 +2,16 @@ package org.spongycastle.asn1; import java.io.InputStream; +/** + * A basic parser for an OCTET STRING object + */ public interface ASN1OctetStringParser extends ASN1Encodable, InMemoryRepresentable { + /** + * Return the content of the OCTET STRING as an InputStream. + * + * @return an InputStream representing the OCTET STRING's content. + */ public InputStream getOctetStream(); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java index 230bc059b..dd6268875 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Primitive.java @@ -2,6 +2,9 @@ package org.spongycastle.asn1; import java.io.IOException; +/** + * Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings. + */ public abstract class ASN1Primitive extends ASN1Object { @@ -47,11 +50,21 @@ public abstract class ASN1Primitive return this; } + /** + * Return the current object as one which encodes using Distinguished Encoding Rules. + * + * @return a DER version of this. + */ ASN1Primitive toDERObject() { return this; } + /** + * Return the current object as one which encodes using Definite Length encoding. + * + * @return a DL version of this. + */ ASN1Primitive toDLObject() { return this; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java index b2942fb1b..1de4e3158 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Sequence.java @@ -4,16 +4,64 @@ import java.io.IOException; import java.util.Enumeration; import java.util.Vector; +/** + * ASN.1SEQUENCE
and SEQUENCE OF
constructs.
+ * + * DER form is always definite form length fields, while + * BER support uses indefinite form. + *
X.690
+ *8: Basic encoding rules
+ *8.9 Encoding of a sequence value
+ * 8.9.1 The encoding of a sequence value shall be constructed. + *+ * 8.9.2 The contents octets shall consist of the complete + * encoding of one data value from each of the types listed in + * the ASN.1 definition of the sequence type, in the order of + * their appearance in the definition, unless the type was referenced + * with the keyword OPTIONAL or the keyword DEFAULT. + *
+ * 8.9.3 The encoding of a data value may, but need not, + * be present for a type which was referenced with the keyword + * OPTIONAL or the keyword DEFAULT. + * If present, it shall appear in the encoding at the point + * corresponding to the appearance of the type in the ASN.1 definition. + *
+ * 8.10 Encoding of a sequence-of value + *
+ * 8.10.1 The encoding of a sequence-of value shall be constructed. + *
+ * 8.10.2 The contents octets shall consist of zero, + * one or more complete encodings of data values from the type listed in + * the ASN.1 definition. + *
+ * 8.10.3 The order of the encodings of the data values shall be + * the same as the order of the data values in the sequence-of value to + * be encoded. + *
+ *9: Canonical encoding rules
+ *9.1 Length forms
+ * If the encoding is constructed, it shall employ the indefinite length form. + * If the encoding is primitive, it shall include the fewest length octets necessary. + * [Contrast with 8.1.3.2 b).] + * + *11: Restrictions on BER employed by both CER and DER
+ *11.5 Set and sequence components with default value
+ * The encoding of a set value or sequence value shall not include + * an encoding for any component value which is equal to + * its default value. + */ public abstract class ASN1Sequence extends ASN1Primitive { protected Vector seq = new Vector(); /** - * return an ASN1Sequence from the given object. + * Return an ASN1Sequence from the given object. * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. + * @return an ASN1Sequence instance, or null. */ public static ASN1Sequence getInstance( Object obj) @@ -65,6 +113,7 @@ public abstract class ASN1Sequence * false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return an ASN1Sequence instance. */ public static ASN1Sequence getInstance( ASN1TaggedObject obj, @@ -110,14 +159,15 @@ public abstract class ASN1Sequence } /** - * create an empty sequence + * Create an empty sequence */ protected ASN1Sequence() { } /** - * create a sequence containing one object + * Create a sequence containing one object + * @param obj the object to be put in the SEQUENCE. */ protected ASN1Sequence( ASN1Encodable obj) @@ -126,7 +176,8 @@ public abstract class ASN1Sequence } /** - * create a sequence containing a vector of objects. + * Create a sequence containing a vector of objects. + * @param v the vector of objects to be put in the SEQUENCE */ protected ASN1Sequence( ASN1EncodableVector v) @@ -138,7 +189,7 @@ public abstract class ASN1Sequence } /** - * create a sequence containing a vector of objects. + * Create a sequence containing a vector of objects. */ protected ASN1Sequence( ASN1Encodable[] array) @@ -209,7 +260,7 @@ public abstract class ASN1Sequence } /** - * return the object at the sequence position indicated by index. + * Return the object at the sequence position indicated by index. * * @param index the sequence number (starting at zero) of the object * @return the object at the sequence position indicated by index. @@ -221,7 +272,7 @@ public abstract class ASN1Sequence } /** - * return the number of objects in this sequence. + * Return the number of objects in this sequence. * * @return the number of objects in this sequence. */ @@ -290,6 +341,10 @@ public abstract class ASN1Sequence return encObj; } + /** + * Change current SEQUENCE object to be encoded as {@link DERSequence}. + * This is part of Distinguished Encoding Rules form serialization. + */ ASN1Primitive toDERObject() { ASN1Sequence derSeq = new DERSequence(); @@ -299,6 +354,10 @@ public abstract class ASN1Sequence return derSeq; } + /** + * Change current SEQUENCE object to be encoded as {@link DLSequence}. + * This is part of Direct Length form serialization. + */ ASN1Primitive toDLObject() { ASN1Sequence dlSeq = new DLSequence(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java index c2904a32b..2997acdcf 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SequenceParser.java @@ -2,9 +2,18 @@ package org.spongycastle.asn1; import java.io.IOException; +/** + * A basic parser for a SEQUENCE object + */ public interface ASN1SequenceParser extends ASN1Encodable, InMemoryRepresentable { + /** + * Read the next object from the underlying object representing a SEQUENCE. + * + * @throws IOException for bad input stream. + * @return the next object, null if we are at the end. + */ ASN1Encodable readObject() throws IOException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Set.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Set.java index 5cc1163bc..0bc925470 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Set.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1Set.java @@ -5,7 +5,94 @@ import java.io.IOException; import java.util.Enumeration; import java.util.Vector; -abstract public class ASN1Set +/** + * ASN.1SET
and SET OF
constructs.
+ * + * Note: This does not know which syntax the set is! + * (The difference: ordering of SET elements or not ordering.) + *
+ * DER form is always definite form length fields, while + * BER support uses indefinite form. + *
+ * The CER form support does not exist. + *
+ *
+ * 8.11.2 The contents octets shall consist of the complete + * encoding of a data value from each of the types listed in the + * ASN.1 definition of the set type, in an order chosen by the sender, + * unless the type was referenced with the keyword + * OPTIONAL or the keyword DEFAULT. + *
+ * 8.11.3 The encoding of a data value may, but need not, + * be present for a type which was referenced with the keyword + * OPTIONAL or the keyword DEFAULT. + *
+ * NOTE — The order of data values in a set value is not significant, + * and places no constraints on the order during transfer + *+ *
+ * 8.12.2 The text of 8.10.2 applies: + * The contents octets shall consist of zero, + * one or more complete encodings of data values from the type listed in + * the ASN.1 definition. + *
+ * 8.12.3 The order of data values need not be preserved by + * the encoding and subsequent decoding. + * + *
+ * NOTE — Where a component of the set is an untagged choice type, + * the location of that component in the ordering will depend on + * the tag of the choice component being encoded. + *+ * + *
+ * The encodings of the component values of a set-of value + * shall appear in ascending order, the encodings being compared + * as octet strings with the shorter components being padded at + * their trailing end with 0-octets. + *
+ * NOTE — The padding octets are for comparison purposes only + * and do not appear in the encodings. + *+ */ +public abstract class ASN1Set extends ASN1Primitive { private Vector set = new Vector(); @@ -16,6 +103,7 @@ abstract public class ASN1Set * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. + * @return an ASN1Set instance, or null. */ public static ASN1Set getInstance( Object obj) @@ -67,6 +155,7 @@ abstract public class ASN1Set * false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return an ASN1Set instance. */ public static ASN1Set getInstance( ASN1TaggedObject obj, @@ -135,6 +224,7 @@ abstract public class ASN1Set /** * create a sequence containing one object + * @param obj object to be added to the SET. */ protected ASN1Set( ASN1Encodable obj) @@ -144,6 +234,8 @@ abstract public class ASN1Set /** * create a sequence containing a vector of objects. + * @param v a vector of objects to make up the SET. + * @param doSort true if should be sorted DER style, false otherwise. */ protected ASN1Set( ASN1EncodableVector v, @@ -275,6 +367,10 @@ abstract public class ASN1Set return hashCode; } + /** + * Change current SET object to be encoded as {@link DERSet}. + * This is part of Distinguished Encoding Rules form serialization. + */ ASN1Primitive toDERObject() { if (isSorted) @@ -304,6 +400,10 @@ abstract public class ASN1Set } } + /** + * Change current SET object to be encoded as {@link DLSet}. + * This is part of Direct Length form serialization. + */ ASN1Primitive toDLObject() { ASN1Set derSet = new DLSet(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java index adbe42069..649e968ae 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1SetParser.java @@ -2,9 +2,18 @@ package org.spongycastle.asn1; import java.io.IOException; +/** + * A basic parser for a SET object + */ public interface ASN1SetParser extends ASN1Encodable, InMemoryRepresentable { + /** + * Read the next object from the underlying object representing a SET. + * + * @throws IOException for bad input stream. + * @return the next object, null if we are at the end. + */ public ASN1Encodable readObject() throws IOException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java index 0b7de8f81..e5875b528 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1StreamParser.java @@ -4,6 +4,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +/** + * A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters. + */ public class ASN1StreamParser { private final InputStream _in; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java index d011b7d92..2f96041ff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ASN1UTCTime.java @@ -1,22 +1,314 @@ package org.spongycastle.asn1; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; +import java.util.SimpleTimeZone; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Strings; + +/** +- * UTC time object. + * Internal facade of {@link ASN1UTCTime}. + *
+ * This datatype is valid only from 1950-01-01 00:00:00 UTC until 2049-12-31 23:59:59 UTC. + *
+ *
X.690
+ *11: Restrictions on BER employed by both CER and DER
+ *11.8 UTCTime
+ * 11.8.1 The encoding shall terminate with "Z", + * as described in the ITU-T X.680 | ISO/IEC 8824-1 clause on UTCTime. + *+ * 11.8.2 The seconds element shall always be present. + *
+ * 11.8.3 Midnight (GMT) shall be represented in the form: + *
+ * "YYMMDD000000Z" + *+ * where "YYMMDD" represents the day following the midnight in question. + */ public class ASN1UTCTime - extends DERUTCTime + extends ASN1Primitive { - ASN1UTCTime(byte[] bytes) + private byte[] time; + + /** + * return an UTC Time from the passed in object. + * + * @param obj an ASN1UTCTime or an object that can be converted into one. + * @exception IllegalArgumentException if the object cannot be converted. + * @return an ASN1UTCTime instance, or null. + */ + public static ASN1UTCTime getInstance( + Object obj) { - super(bytes); + if (obj == null || obj instanceof ASN1UTCTime) + { + return (ASN1UTCTime)obj; + } + + if (obj instanceof byte[]) + { + try + { + return (ASN1UTCTime)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } + + throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } - public ASN1UTCTime(Date time) + /** + * return an UTC Time 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. + * @return an ASN1UTCTime instance, or null. + */ + public static ASN1UTCTime getInstance( + ASN1TaggedObject obj, + boolean explicit) { - super(time); + ASN1Object o = obj.getObject(); + + if (explicit || o instanceof ASN1UTCTime) + { + return getInstance(o); + } + else + { + return new ASN1UTCTime(((ASN1OctetString)o).getOctets()); + } } - public ASN1UTCTime(String time) + /** + * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were + * never encoded. When you're creating one of these objects from scratch, that's + * what you want to use, otherwise we'll try to deal with whatever gets read from + * the input stream... (this is why the input format is different from the getTime() + * method output). + *
+ * + * @param time the time string. + */ + public ASN1UTCTime( + String time) { - super(time); + this.time = Strings.toByteArray(time); + try + { + this.getDate(); + } + catch (ParseException e) + { + throw new IllegalArgumentException("invalid date string: " + e.getMessage()); + } + } + + /** + * base constructor from a java.util.date object + * @param time the Date to build the time from. + */ + public ASN1UTCTime( + Date time) + { + SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'"); + + dateF.setTimeZone(new SimpleTimeZone(0,"Z")); + + this.time = Strings.toByteArray(dateF.format(time)); + } + + /** + * Base constructor from a java.util.date and Locale - you may need to use this if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. + * + * @param time a date object representing the time of interest. + * @param locale an appropriate Locale for producing an ASN.1 UTCTime value. + */ + public ASN1UTCTime( + Date time, + Locale locale) + { + SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale); + + dateF.setTimeZone(new SimpleTimeZone(0,"Z")); + + this.time = Strings.toByteArray(dateF.format(time)); + } + + ASN1UTCTime( + byte[] time) + { + this.time = time; + } + + /** + * return the time as a date based on whatever a 2 digit year will return. For + * standardised processing use getAdjustedDate(). + * + * @return the resulting date + * @exception ParseException if the date string cannot be parsed. + */ + public Date getDate() + throws ParseException + { + SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz"); + + return dateF.parse(getTime()); + } + + /** + * return the time as an adjusted date + * in the range of 1950 - 2049. + * + * @return a date in the range of 1950 to 2049. + * @exception ParseException if the date string cannot be parsed. + */ + public Date getAdjustedDate() + throws ParseException + { + SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); + + dateF.setTimeZone(new SimpleTimeZone(0, "Z")); + + return dateF.parse(getAdjustedTime()); + } + + /** + * return the time - always in the form of + * YYMMDDhhmmssGMT(+hh:mm|-hh:mm). + *
+ * Normally in a certificate we would expect "Z" rather than "GMT", + * however adding the "GMT" means we can just use: + *
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz"); + *+ * To read in the time and get a date which is compatible with our local + * time zone. + *
+ * Note: In some cases, due to the local date processing, this + * may lead to unexpected results. If you want to stick the normal + * convention of 1950 to 2049 use the getAdjustedTime() method. + */ + public String getTime() + { + String stime = Strings.fromByteArray(time); + + // + // standardise the format. + // + if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0) + { + if (stime.length() == 11) + { + return stime.substring(0, 10) + "00GMT+00:00"; + } + else + { + return stime.substring(0, 12) + "GMT+00:00"; + } + } + else + { + int index = stime.indexOf('-'); + if (index < 0) + { + index = stime.indexOf('+'); + } + String d = stime; + + if (index == stime.length() - 3) + { + d += "00"; + } + + if (index == 10) + { + return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15); + } + else + { + return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17); + } + } + } + + /** + * return a time string as an adjusted date with a 4 digit year. This goes + * in the range of 1950 - 2049. + */ + public String getAdjustedTime() + { + String d = this.getTime(); + + if (d.charAt(0) < '5') + { + return "20" + d; + } + else + { + return "19" + d; + } + } + + boolean isConstructed() + { + return false; + } + + int encodedLength() + { + int length = time.length; + + return 1 + StreamUtil.calculateBodyLength(length) + length; + } + + void encode( + ASN1OutputStream out) + throws IOException + { + out.write(BERTags.UTC_TIME); + + int length = time.length; + + out.writeLength(length); + + for (int i = 0; i != length; i++) + { + out.write((byte)time[i]); + } + } + + boolean asn1Equals( + ASN1Primitive o) + { + if (!(o instanceof ASN1UTCTime)) + { + return false; + } + + return Arrays.areEqual(time, ((ASN1UTCTime)o).time); + } + + public int hashCode() + { + return Arrays.hashCode(time); + } + + public String toString() + { + return Strings.fromByteArray(time); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java index 63f99a34c..d3b40e030 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERApplicationSpecific.java @@ -103,15 +103,6 @@ public class DERApplicationSpecific throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage()); } } - else if (obj instanceof ASN1Encodable) - { - ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive(); - - if (primitive instanceof ASN1Sequence) - { - return (DERApplicationSpecific)primitive; - } - } throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBMPString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBMPString.java index 58dbb36a5..ad752583e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBMPString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBMPString.java @@ -18,6 +18,7 @@ public class DERBMPString * * @param obj the object we want converted. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERBMPString instance, or null. */ public static DERBMPString getInstance( Object obj) @@ -50,6 +51,7 @@ public class DERBMPString * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERBMPString instance. */ public static DERBMPString getInstance( ASN1TaggedObject obj, @@ -69,6 +71,7 @@ public class DERBMPString /** * basic constructor - byte encoded string. + * @param string the encoded BMP STRING to wrap. */ DERBMPString( byte[] string) @@ -90,6 +93,7 @@ public class DERBMPString /** * basic constructor + * @param string a String to wrap as a BMP STRING. */ public DERBMPString( String string) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBitString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBitString.java index 6fbc2db95..9a2d2d03e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBitString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBitString.java @@ -18,7 +18,8 @@ public class DERBitString protected int padBits; /** - * return the correct number of pad bits for a bit string defined in + * @param bitString an int containing the BIT STRING + * @return the correct number of pad bits for a bit string defined in * a 32 bit constant */ static protected int getPadBits( @@ -66,7 +67,8 @@ public class DERBitString } /** - * return the correct number of bytes for a bit string defined in + * @param bitString an int containing the BIT STRING + * @return the correct number of bytes for a bit string defined in * a 32 bit constant */ static protected byte[] getBytes(int bitString) @@ -93,7 +95,9 @@ public class DERBitString /** * return a Bit String from the passed in object * + * @param obj a DERBitString or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERBitString instance, or null. */ public static DERBitString getInstance( Object obj) @@ -114,6 +118,7 @@ public class DERBitString * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERBitString instance, or null. */ public static DERBitString getInstance( ASN1TaggedObject obj, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBoolean.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBoolean.java index c176bfb73..9e101c45c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBoolean.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERBoolean.java @@ -1,179 +1,22 @@ package org.spongycastle.asn1; -import java.io.IOException; - -import org.spongycastle.util.Arrays; - +/** + * @deprecated use ASN1Boolean + */ public class DERBoolean - extends ASN1Primitive + extends ASN1Boolean { - private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff }; - private static final byte[] FALSE_VALUE = new byte[] { 0 }; - - private byte[] value; - - public static final ASN1Boolean FALSE = new ASN1Boolean(false); - public static final ASN1Boolean TRUE = new ASN1Boolean(true); - - - /** - * return a boolean from the passed in object. - * - * @exception IllegalArgumentException if the object cannot be converted. - */ - public static ASN1Boolean getInstance( - Object obj) - { - if (obj == null || obj instanceof ASN1Boolean) - { - return (ASN1Boolean)obj; - } - - if (obj instanceof DERBoolean) - { - return ((DERBoolean)obj).isTrue() ? DERBoolean.TRUE : DERBoolean.FALSE; - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); - } - - /** - * return a ASN1Boolean from the passed in boolean. - */ - public static ASN1Boolean getInstance( - boolean value) - { - return (value ? TRUE : FALSE); - } - - /** - * return a ASN1Boolean from the passed in boolean. - */ - public static ASN1Boolean getInstance( - int value) - { - return (value != 0 ? TRUE : FALSE); - } - - /** - * return a Boolean 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 ASN1Boolean getInstance( - ASN1TaggedObject obj, - boolean explicit) - { - ASN1Primitive o = obj.getObject(); - - if (explicit || o instanceof DERBoolean) - { - return getInstance(o); - } - else - { - return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets()); - } - } - - DERBoolean( - byte[] value) - { - if (value.length != 1) - { - throw new IllegalArgumentException("byte value should have 1 byte in it"); - } - - if (value[0] == 0) - { - this.value = FALSE_VALUE; - } - else if (value[0] == 0xff) - { - this.value = TRUE_VALUE; - } - else - { - this.value = Arrays.clone(value); - } - } - /** * @deprecated use getInstance(boolean) method. * @param value */ - public DERBoolean( - boolean value) + public DERBoolean(boolean value) { - this.value = (value) ? TRUE_VALUE : FALSE_VALUE; + super(value); } - public boolean isTrue() + DERBoolean(byte[] value) { - return (value[0] != 0); - } - - boolean isConstructed() - { - return false; - } - - int encodedLength() - { - return 3; - } - - void encode( - ASN1OutputStream out) - throws IOException - { - out.writeEncoded(BERTags.BOOLEAN, value); - } - - protected boolean asn1Equals( - ASN1Primitive o) - { - if ((o == null) || !(o instanceof DERBoolean)) - { - return false; - } - - return (value[0] == ((DERBoolean)o).value[0]); - } - - public int hashCode() - { - return value[0]; - } - - - public String toString() - { - return (value[0] != 0) ? "TRUE" : "FALSE"; - } - - static ASN1Boolean fromOctetString(byte[] value) - { - if (value.length != 1) - { - throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it"); - } - - if (value[0] == 0) - { - return FALSE; - } - else if (value[0] == 0xff) - { - return TRUE; - } - else - { - return new ASN1Boolean(value); - } + super(value); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java index 7503c8992..833c091b9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DEREnumerated.java @@ -1,170 +1,37 @@ package org.spongycastle.asn1; -import java.io.IOException; import java.math.BigInteger; -import org.spongycastle.util.Arrays; - /** - * Use ASN1Enumerated instead of this. + * @deprecated Use ASN1Enumerated instead of this. */ public class DEREnumerated - extends ASN1Primitive + extends ASN1Enumerated { - byte[] bytes; - - /** - * return an integer from the passed in object - * - * @exception IllegalArgumentException if the object cannot be converted. - */ - public static ASN1Enumerated getInstance( - Object obj) - { - if (obj == null || obj instanceof ASN1Enumerated) - { - return (ASN1Enumerated)obj; - } - - if (obj instanceof DEREnumerated) - { - return new ASN1Enumerated(((DEREnumerated)obj).getValue()); - } - - if (obj instanceof byte[]) - { - try - { - return (ASN1Enumerated)fromByteArray((byte[])obj); - } - catch (Exception e) - { - throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); - } - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); - } - - /** - * return an Enumerated 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 ASN1Enumerated getInstance( - ASN1TaggedObject obj, - boolean explicit) - { - ASN1Primitive o = obj.getObject(); - - if (explicit || o instanceof DEREnumerated) - { - return getInstance(o); - } - else - { - return fromOctetString(((ASN1OctetString)o).getOctets()); - } - } - /** + * @param bytes the value of this enumerated as an encoded BigInteger (signed). * @deprecated use ASN1Enumerated */ - public DEREnumerated( - int value) + DEREnumerated(byte[] bytes) { - bytes = BigInteger.valueOf(value).toByteArray(); + super(bytes); } /** + * @param value the value of this enumerated. * @deprecated use ASN1Enumerated */ - public DEREnumerated( - BigInteger value) + public DEREnumerated(BigInteger value) { - bytes = value.toByteArray(); + super(value); } /** + * @param value the value of this enumerated. * @deprecated use ASN1Enumerated */ - public DEREnumerated( - byte[] bytes) + public DEREnumerated(int value) { - this.bytes = bytes; - } - - public BigInteger getValue() - { - return new BigInteger(bytes); - } - - boolean isConstructed() - { - return false; - } - - int encodedLength() - { - return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; - } - - void encode( - ASN1OutputStream out) - throws IOException - { - out.writeEncoded(BERTags.ENUMERATED, bytes); - } - - boolean asn1Equals( - ASN1Primitive o) - { - if (!(o instanceof DEREnumerated)) - { - return false; - } - - DEREnumerated other = (DEREnumerated)o; - - return Arrays.areEqual(this.bytes, other.bytes); - } - - public int hashCode() - { - return Arrays.hashCode(bytes); - } - - private static ASN1Enumerated[] cache = new ASN1Enumerated[12]; - - static ASN1Enumerated fromOctetString(byte[] enc) - { - if (enc.length > 1) - { - return new ASN1Enumerated(Arrays.clone(enc)); - } - - if (enc.length == 0) - { - throw new IllegalArgumentException("ENUMERATED has zero length"); - } - int value = enc[0] & 0xff; - - if (value >= cache.length) - { - return new ASN1Enumerated(Arrays.clone(enc)); - } - - ASN1Enumerated possibleMatch = cache[value]; - - if (possibleMatch == null) - { - possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc)); - } - - return possibleMatch; + super(value); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java index e740769d1..b61f6b0d5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERGeneralizedTime.java @@ -1,350 +1,28 @@ package org.spongycastle.asn1; -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.SimpleTimeZone; -import java.util.TimeZone; - -import org.spongycastle.util.Arrays; -import org.spongycastle.util.Strings; /** - * Generalized time object. + * DER Generalized time object. */ public class DERGeneralizedTime - extends ASN1Primitive + extends ASN1GeneralizedTime { - private byte[] time; - /** - * return a generalized time from the passed in object - * - * @exception IllegalArgumentException if the object cannot be converted. - */ - public static ASN1GeneralizedTime getInstance( - Object obj) + DERGeneralizedTime(byte[] bytes) { - if (obj == null || obj instanceof ASN1GeneralizedTime) - { - return (ASN1GeneralizedTime)obj; - } - - if (obj instanceof DERGeneralizedTime) - { - return new ASN1GeneralizedTime(((DERGeneralizedTime)obj).time); - } - - if (obj instanceof byte[]) - { - try - { - return (ASN1GeneralizedTime)fromByteArray((byte[])obj); - } - catch (Exception e) - { - throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); - } - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + super(bytes); } - /** - * return a Generalized Time object 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 ASN1GeneralizedTime getInstance( - ASN1TaggedObject obj, - boolean explicit) + public DERGeneralizedTime(Date time) { - ASN1Primitive o = obj.getObject(); - - if (explicit || o instanceof DERGeneralizedTime) - { - return getInstance(o); - } - else - { - return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets()); - } - } - - /** - * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z - * for local time, or Z+-HHMM on the end, for difference between local - * time and UTC time. The fractional second amount f must consist of at - * least one number with trailing zeroes removed. - * - * @param time the time string. - * @exception IllegalArgumentException if String is an illegal format. - */ - public DERGeneralizedTime( - String time) - { - this.time = Strings.toByteArray(time); - try - { - this.getDate(); - } - catch (ParseException e) - { - throw new IllegalArgumentException("invalid date string: " + e.getMessage()); - } + super(time); } - /** - * base constructor from a java.util.date object - */ - public DERGeneralizedTime( - Date time) + public DERGeneralizedTime(String time) { - SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); - - dateF.setTimeZone(new SimpleTimeZone(0,"Z")); - - this.time = Strings.toByteArray(dateF.format(time)); + super(time); } - DERGeneralizedTime( - byte[] bytes) - { - this.time = bytes; - } - - /** - * Return the time. - * @return The time string as it appeared in the encoded object. - */ - public String getTimeString() - { - return Strings.fromByteArray(time); - } - - /** - * return the time - always in the form of - * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm). - *
- * Normally in a certificate we would expect "Z" rather than "GMT", - * however adding the "GMT" means we can just use: - *
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); - *- * To read in the time and get a date which is compatible with our local - * time zone. - */ - public String getTime() - { - String stime = Strings.fromByteArray(time); - - // - // standardise the format. - // - if (stime.charAt(stime.length() - 1) == 'Z') - { - return stime.substring(0, stime.length() - 1) + "GMT+00:00"; - } - else - { - int signPos = stime.length() - 5; - char sign = stime.charAt(signPos); - if (sign == '-' || sign == '+') - { - return stime.substring(0, signPos) - + "GMT" - + stime.substring(signPos, signPos + 3) - + ":" - + stime.substring(signPos + 3); - } - else - { - signPos = stime.length() - 3; - sign = stime.charAt(signPos); - if (sign == '-' || sign == '+') - { - return stime.substring(0, signPos) - + "GMT" - + stime.substring(signPos) - + ":00"; - } - } - } - return stime + calculateGMTOffset(); - } - - private String calculateGMTOffset() - { - String sign = "+"; - TimeZone timeZone = TimeZone.getDefault(); - int offset = timeZone.getRawOffset(); - if (offset < 0) - { - sign = "-"; - offset = -offset; - } - int hours = offset / (60 * 60 * 1000); - int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000); - - try - { - if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate())) - { - hours += sign.equals("+") ? 1 : -1; - } - } - catch (ParseException e) - { - // we'll do our best and ignore daylight savings - } - - return "GMT" + sign + convert(hours) + ":" + convert(minutes); - } - - private String convert(int time) - { - if (time < 10) - { - return "0" + time; - } - - return Integer.toString(time); - } - - public Date getDate() - throws ParseException - { - SimpleDateFormat dateF; - String stime = Strings.fromByteArray(time); - String d = stime; - - if (stime.endsWith("Z")) - { - if (hasFractionalSeconds()) - { - dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'"); - } - else - { - dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); - } - - dateF.setTimeZone(new SimpleTimeZone(0, "Z")); - } - else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0) - { - d = this.getTime(); - if (hasFractionalSeconds()) - { - dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz"); - } - else - { - dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); - } - - dateF.setTimeZone(new SimpleTimeZone(0, "Z")); - } - else - { - if (hasFractionalSeconds()) - { - dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); - } - else - { - dateF = new SimpleDateFormat("yyyyMMddHHmmss"); - } - - dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); - } - - if (hasFractionalSeconds()) - { - // java misinterprets extra digits as being milliseconds... - String frac = d.substring(14); - int index; - for (index = 1; index < frac.length(); index++) - { - char ch = frac.charAt(index); - if (!('0' <= ch && ch <= '9')) - { - break; - } - } - - if (index - 1 > 3) - { - frac = frac.substring(0, 4) + frac.substring(index); - d = d.substring(0, 14) + frac; - } - else if (index - 1 == 1) - { - frac = frac.substring(0, index) + "00" + frac.substring(index); - d = d.substring(0, 14) + frac; - } - else if (index - 1 == 2) - { - frac = frac.substring(0, index) + "0" + frac.substring(index); - d = d.substring(0, 14) + frac; - } - } - - return dateF.parse(d); - } - - private boolean hasFractionalSeconds() - { - for (int i = 0; i != time.length; i++) - { - if (time[i] == '.') - { - if (i == 14) - { - return true; - } - } - } - return false; - } - - boolean isConstructed() - { - return false; - } - - int encodedLength() - { - int length = time.length; - - return 1 + StreamUtil.calculateBodyLength(length) + length; - } - - void encode( - ASN1OutputStream out) - throws IOException - { - out.writeEncoded(BERTags.GENERALIZED_TIME, time); - } - - boolean asn1Equals( - ASN1Primitive o) - { - if (!(o instanceof DERGeneralizedTime)) - { - return false; - } - - return Arrays.areEqual(time, ((DERGeneralizedTime)o).time); - } - - public int hashCode() - { - return Arrays.hashCode(time); - } + // TODO: create proper DER encoding. } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERIA5String.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERIA5String.java index f4a5905fe..1ff1c7ac5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERIA5String.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERIA5String.java @@ -17,7 +17,9 @@ public class DERIA5String /** * return a IA5 string from the passed in object * + * @param obj a DERIA5String or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERIA5String instance, or null. */ public static DERIA5String getInstance( Object obj) @@ -50,6 +52,7 @@ public class DERIA5String * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERIA5String instance, or null. */ public static DERIA5String getInstance( ASN1TaggedObject obj, @@ -69,6 +72,7 @@ public class DERIA5String /** * basic constructor - with bytes. + * @param string the byte encoding of the characters making up the string. */ DERIA5String( byte[] string) @@ -78,6 +82,7 @@ public class DERIA5String /** * basic constructor - without validation. + * @param string the base string to use.. */ public DERIA5String( String string) @@ -163,7 +168,8 @@ public class DERIA5String * return true if the passed in String can be represented without * loss as an IA5String, false otherwise. * - * @return true if in printable set, false otherwise. + * @param str the string to check. + * @return true if character set in IA5String set, false otherwise. */ public static boolean isIA5String( String str) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERInteger.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERInteger.java index 77051cfbe..3cc465d3c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERInteger.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERInteger.java @@ -1,160 +1,30 @@ package org.spongycastle.asn1; -import java.io.IOException; import java.math.BigInteger; -import org.spongycastle.util.Arrays; - /** - * Use ASN1Integer instead of this, + * @deprecated Use ASN1Integer instead of this, */ public class DERInteger - extends ASN1Primitive + extends ASN1Integer { - byte[] bytes; - /** - * return an integer from the passed in object + * Constructor from a byte array containing a signed representation of the number. * - * @exception IllegalArgumentException if the object cannot be converted. + * @param bytes a byte array containing the signed number.A copy is made of the byte array. */ - public static ASN1Integer getInstance( - Object obj) + public DERInteger(byte[] bytes) { - if (obj == null || obj instanceof ASN1Integer) - { - return (ASN1Integer)obj; - } - if (obj instanceof DERInteger) - { - return new ASN1Integer((((DERInteger)obj).getValue())); - } - - if (obj instanceof byte[]) - { - try - { - return (ASN1Integer)fromByteArray((byte[])obj); - } - catch (Exception e) - { - throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); - } - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + super(bytes, true); } - /** - * return an Integer 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 ASN1Integer getInstance( - ASN1TaggedObject obj, - boolean explicit) + public DERInteger(BigInteger value) { - ASN1Primitive o = obj.getObject(); - - if (explicit || o instanceof DERInteger) - { - return getInstance(o); - } - else - { - return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets()); - } + super(value); } - /** - * @deprecated use ASN1Integer constructor - */ - public DERInteger( - long value) + public DERInteger(long value) { - bytes = BigInteger.valueOf(value).toByteArray(); - } - - /** - * @deprecated use ASN1Integer constructor - */ - public DERInteger( - BigInteger value) - { - bytes = value.toByteArray(); - } - - /** - * @deprecated use ASN1Integer constructor - */ - public DERInteger( - byte[] bytes) - { - this.bytes = bytes; - } - - public BigInteger getValue() - { - return new BigInteger(bytes); - } - - /** - * in some cases positive values get crammed into a space, - * that's not quite big enough... - */ - public BigInteger getPositiveValue() - { - return new BigInteger(1, bytes); - } - - boolean isConstructed() - { - return false; - } - - int encodedLength() - { - return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; - } - - void encode( - ASN1OutputStream out) - throws IOException - { - out.writeEncoded(BERTags.INTEGER, bytes); - } - - public int hashCode() - { - int value = 0; - - for (int i = 0; i != bytes.length; i++) - { - value ^= (bytes[i] & 0xff) << (i % 4); - } - - return value; - } - - boolean asn1Equals( - ASN1Primitive o) - { - if (!(o instanceof DERInteger)) - { - return false; - } - - DERInteger other = (DERInteger)o; - - return Arrays.areEqual(bytes, other.bytes); - } - - public String toString() - { - return getValue().toString(); + super(value); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERNumericString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERNumericString.java index d092fce0b..3835927dc 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERNumericString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERNumericString.java @@ -17,7 +17,9 @@ public class DERNumericString /** * return a Numeric string from the passed in object * + * @param obj a DERNumericString or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERNumericString instance, or null */ public static DERNumericString getInstance( Object obj) @@ -50,6 +52,7 @@ public class DERNumericString * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERNumericString instance, or null. */ public static DERNumericString getInstance( ASN1TaggedObject obj, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java index dd0106560..cf75640be 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERObjectIdentifier.java @@ -1,446 +1,24 @@ package org.spongycastle.asn1; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; - -import org.spongycastle.util.Arrays; - /** - * Use ASN1ObjectIdentifier instead of this, + * + * @deprecated Use ASN1ObjectIdentifier instead of this, */ public class DERObjectIdentifier - extends ASN1Primitive + extends ASN1ObjectIdentifier { - String identifier; - - private byte[] body; - - /** - * return an OID from the passed in object - * - * @throws IllegalArgumentException if the object cannot be converted. - */ - public static ASN1ObjectIdentifier getInstance( - Object obj) + public DERObjectIdentifier(String identifier) { - 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[]) - { - byte[] enc = (byte[])obj; - if (enc[0] == BERTags.OBJECT_IDENTIFIER) - { - try - { - return (ASN1ObjectIdentifier)fromByteArray(enc); - } - catch (IOException e) - { - throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage()); - } - } - else - { // TODO: this really shouldn't be supported here... - return ASN1ObjectIdentifier.fromOctetString((byte[])obj); - } - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + super(identifier); } - /** - * 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. - * @throws IllegalArgumentException if the tagged object cannot - * be converted. - */ - public static ASN1ObjectIdentifier getInstance( - ASN1TaggedObject obj, - boolean explicit) + DERObjectIdentifier(byte[] bytes) { - ASN1Primitive o = obj.getObject(); - - if (explicit || o instanceof DERObjectIdentifier) - { - return getInstance(o); - } - else - { - return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets()); - } + super(bytes); } - private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f; - - DERObjectIdentifier( - byte[] bytes) + DERObjectIdentifier(ASN1ObjectIdentifier oid, String branch) { - 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); - } - - /** - * @deprecated use ASN1ObjectIdentifier constructor. - */ - 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); + super(oid, branch); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java index 08130759c..cda1c666b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERPrintableString.java @@ -16,8 +16,10 @@ public class DERPrintableString /** * return a printable string from the passed in object. - * + * + * @param obj a DERPrintableString or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERPrintableString instance, or null. */ public static DERPrintableString getInstance( Object obj) @@ -50,6 +52,7 @@ public class DERPrintableString * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERPrintableString instance, or null. */ public static DERPrintableString getInstance( ASN1TaggedObject obj, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61String.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61String.java index f931c8b8b..bdcff1d23 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61String.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61String.java @@ -18,7 +18,9 @@ public class DERT61String /** * return a T61 string from the passed in object. * + * @param obj a DERT61String or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERT61String instance, or null */ public static DERT61String getInstance( Object obj) @@ -51,6 +53,7 @@ public class DERT61String * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERT61String instance, or null */ public static DERT61String getInstance( ASN1TaggedObject obj, @@ -70,6 +73,8 @@ public class DERT61String /** * basic constructor - string encoded as a sequence of bytes. + * + * @param string the byte encoding of the string to be wrapped. */ public DERT61String( byte[] string) @@ -79,6 +84,8 @@ public class DERT61String /** * basic constructor - with string 8 bit assumed. + * + * @param string the string to be wrapped. */ public DERT61String( String string) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java index 4a240920b..4496cb70a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERT61UTF8String.java @@ -18,7 +18,9 @@ public class DERT61UTF8String /** * return a T61 string from the passed in object. UTF-8 Encoding is assumed in this case. * + * @param obj a DERT61UTF8String or an object that can be converted into one. * @throws IllegalArgumentException if the object cannot be converted. + * @return a DERT61UTF8String instance, or null */ public static DERT61UTF8String getInstance( Object obj) @@ -56,6 +58,7 @@ public class DERT61UTF8String * tagged false otherwise. * @throws IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERT61UTF8String instance, or null */ public static DERT61UTF8String getInstance( ASN1TaggedObject obj, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java index 3f8aa31d4..32260f287 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTCTime.java @@ -1,278 +1,27 @@ package org.spongycastle.asn1; -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.SimpleTimeZone; - -import org.spongycastle.util.Arrays; -import org.spongycastle.util.Strings; /** - * UTC time object. + * DER UTC time object. */ public class DERUTCTime - extends ASN1Primitive + extends ASN1UTCTime { - private byte[] time; - - /** - * return an UTC Time from the passed in object. - * - * @exception IllegalArgumentException if the object cannot be converted. - */ - public static ASN1UTCTime getInstance( - Object obj) + DERUTCTime(byte[] bytes) { - if (obj == null || obj instanceof ASN1UTCTime) - { - return (ASN1UTCTime)obj; - } - - if (obj instanceof DERUTCTime) - { - return new ASN1UTCTime(((DERUTCTime)obj).time); - } - - if (obj instanceof byte[]) - { - try - { - return (ASN1UTCTime)fromByteArray((byte[])obj); - } - catch (Exception e) - { - throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); - } - } - - throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); + super(bytes); } - /** - * return an UTC Time 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 ASN1UTCTime getInstance( - ASN1TaggedObject obj, - boolean explicit) + public DERUTCTime(Date time) { - ASN1Object o = obj.getObject(); - - if (explicit || o instanceof ASN1UTCTime) - { - return getInstance(o); - } - else - { - return new ASN1UTCTime(((ASN1OctetString)o).getOctets()); - } - } - - /** - * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were - * never encoded. When you're creating one of these objects from scratch, that's - * what you want to use, otherwise we'll try to deal with whatever gets read from - * the input stream... (this is why the input format is different from the getTime() - * method output). - *
- * - * @param time the time string. - */ - public DERUTCTime( - String time) - { - this.time = Strings.toByteArray(time); - try - { - this.getDate(); - } - catch (ParseException e) - { - throw new IllegalArgumentException("invalid date string: " + e.getMessage()); - } + super(time); } - /** - * base constructer from a java.util.date object - */ - public DERUTCTime( - Date time) + public DERUTCTime(String time) { - SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'"); - - dateF.setTimeZone(new SimpleTimeZone(0,"Z")); - - this.time = Strings.toByteArray(dateF.format(time)); + super(time); } - DERUTCTime( - byte[] time) - { - this.time = time; - } - - /** - * return the time as a date based on whatever a 2 digit year will return. For - * standardised processing use getAdjustedDate(). - * - * @return the resulting date - * @exception ParseException if the date string cannot be parsed. - */ - public Date getDate() - throws ParseException - { - SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz"); - - return dateF.parse(getTime()); - } - - /** - * return the time as an adjusted date - * in the range of 1950 - 2049. - * - * @return a date in the range of 1950 to 2049. - * @exception ParseException if the date string cannot be parsed. - */ - public Date getAdjustedDate() - throws ParseException - { - SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); - - dateF.setTimeZone(new SimpleTimeZone(0, "Z")); - - return dateF.parse(getAdjustedTime()); - } - - /** - * return the time - always in the form of - * YYMMDDhhmmssGMT(+hh:mm|-hh:mm). - *
- * Normally in a certificate we would expect "Z" rather than "GMT", - * however adding the "GMT" means we can just use: - *
- * dateF = new SimpleDateFormat("yyMMddHHmmssz"); - *- * To read in the time and get a date which is compatible with our local - * time zone. - *
- * Note: In some cases, due to the local date processing, this - * may lead to unexpected results. If you want to stick the normal - * convention of 1950 to 2049 use the getAdjustedTime() method. - */ - public String getTime() - { - String stime = Strings.fromByteArray(time); - - // - // standardise the format. - // - if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0) - { - if (stime.length() == 11) - { - return stime.substring(0, 10) + "00GMT+00:00"; - } - else - { - return stime.substring(0, 12) + "GMT+00:00"; - } - } - else - { - int index = stime.indexOf('-'); - if (index < 0) - { - index = stime.indexOf('+'); - } - String d = stime; - - if (index == stime.length() - 3) - { - d += "00"; - } - - if (index == 10) - { - return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15); - } - else - { - return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17); - } - } - } - - /** - * return a time string as an adjusted date with a 4 digit year. This goes - * in the range of 1950 - 2049. - */ - public String getAdjustedTime() - { - String d = this.getTime(); - - if (d.charAt(0) < '5') - { - return "20" + d; - } - else - { - return "19" + d; - } - } - - boolean isConstructed() - { - return false; - } - - int encodedLength() - { - int length = time.length; - - return 1 + StreamUtil.calculateBodyLength(length) + length; - } - - void encode( - ASN1OutputStream out) - throws IOException - { - out.write(BERTags.UTC_TIME); - - int length = time.length; - - out.writeLength(length); - - for (int i = 0; i != length; i++) - { - out.write((byte)time[i]); - } - } - - boolean asn1Equals( - ASN1Primitive o) - { - if (!(o instanceof DERUTCTime)) - { - return false; - } - - return Arrays.areEqual(time, ((DERUTCTime)o).time); - } - - public int hashCode() - { - return Arrays.hashCode(time); - } - - public String toString() - { - return Strings.fromByteArray(time); - } + // TODO: create proper DER encoding. } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java index ca22d16ba..6bb235d80 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUTF8String.java @@ -15,10 +15,12 @@ public class DERUTF8String private byte[] string; /** - * return an UTF8 string from the passed in object. - * + * Return an UTF8 string from the passed in object. + * + * @param obj a DERUTF8String or an object that can be converted into one. * @exception IllegalArgumentException * if the object cannot be converted. + * @return a DERUTF8String instance, or null */ public static DERUTF8String getInstance(Object obj) { @@ -44,7 +46,7 @@ public class DERUTF8String } /** - * return an UTF8 String from a tagged object. + * Return an UTF8 String from a tagged object. * * @param obj * the tagged object holding the object we want @@ -53,6 +55,7 @@ public class DERUTF8String * otherwise. * @exception IllegalArgumentException * if the tagged object cannot be converted. + * @return a DERUTF8String instance, or null */ public static DERUTF8String getInstance( ASN1TaggedObject obj, @@ -71,7 +74,7 @@ public class DERUTF8String } /** - * basic constructor - byte encoded string. + * Basic constructor - byte encoded string. */ DERUTF8String(byte[] string) { @@ -79,7 +82,7 @@ public class DERUTF8String } /** - * basic constructor + * Basic constructor */ public DERUTF8String(String string) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java index d7bd6bd57..cc6135104 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERUniversalString.java @@ -18,7 +18,9 @@ public class DERUniversalString /** * return a Universal String from the passed in object. * + * @param obj a DERUniversalString or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERUniversalString instance, or null */ public static DERUniversalString getInstance( Object obj) @@ -51,6 +53,7 @@ public class DERUniversalString * tagged false otherwise. * @exception IllegalArgumentException if the tagged object cannot * be converted. + * @return a DERUniversalString instance, or null */ public static DERUniversalString getInstance( ASN1TaggedObject obj, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java index bf88ec969..b44ddb79c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DERVisibleString.java @@ -6,7 +6,10 @@ import org.spongycastle.util.Arrays; import org.spongycastle.util.Strings; /** - * DER VisibleString object. + * DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126. + *
+ * Explicit character set escape sequences are not allowed. + *
*/ public class DERVisibleString extends ASN1Primitive @@ -15,9 +18,11 @@ public class DERVisibleString private byte[] string; /** - * return a Visible String from the passed in object. + * Return a Visible String from the passed in object. * + * @param obj a DERVisibleString or an object that can be converted into one. * @exception IllegalArgumentException if the object cannot be converted. + * @return a DERVisibleString instance, or null */ public static DERVisibleString getInstance( Object obj) @@ -43,13 +48,14 @@ public class DERVisibleString } /** - * return a Visible String from a tagged object. + * Return a Visible String 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. + * @return a DERVisibleString instance, or null */ public static DERVisibleString getInstance( ASN1TaggedObject obj, @@ -68,7 +74,7 @@ public class DERVisibleString } /** - * basic constructor - byte encoded string. + * Basic constructor - byte encoded string. */ DERVisibleString( byte[] string) @@ -77,7 +83,7 @@ public class DERVisibleString } /** - * basic constructor + * Basic constructor */ public DERVisibleString( String string) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DLSet.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DLSet.java index 9c9ed8b85..071c29e25 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DLSet.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/DLSet.java @@ -11,13 +11,13 @@ import java.util.Enumeration; ** 8.11.2 The contents octets shall consist of the complete * encoding of a data value from each of the types listed in the * ASN.1 definition of the set type, in an order chosen by the sender, * unless the type was referenced with the keyword * OPTIONAL or the keyword DEFAULT. - *
+ ** 8.11.3 The encoding of a data value may, but need not, * be present for a type which was referenced with the keyword * OPTIONAL or the keyword DEFAULT. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java index 0472e8893..9f052204d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/InMemoryRepresentable.java @@ -2,8 +2,15 @@ package org.spongycastle.asn1; import java.io.IOException; +/** + * Interface implemented by objects that can be converted from streaming to in-memory objects. + */ public interface InMemoryRepresentable { + /** + * Get the in-memory representation of the ASN.1 object. + * @throws IOException for bad input data. + */ ASN1Primitive getLoadedObject() throws IOException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java new file mode 100644 index 000000000..e9bd0ca26 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/bsi/BSIObjectIdentifiers.java @@ -0,0 +1,35 @@ +package org.spongycastle.asn1.bsi; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; + +/** + * See https://www.bsi.bund.de/cae/servlet/contentblob/471398/publicationFile/30615/BSI-TR-03111_pdf.pdf + */ +public interface BSIObjectIdentifiers +{ + static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7"); + + /* 0.4.0.127.0.7.1.1 */ + static final ASN1ObjectIdentifier id_ecc = bsi_de.branch("1.1"); + + /* 0.4.0.127.0.7.1.1.4.1 */ + static final ASN1ObjectIdentifier ecdsa_plain_signatures = id_ecc.branch("4.1"); + + /* 0.4.0.127.0.7.1.1.4.1.1 */ + static final ASN1ObjectIdentifier ecdsa_plain_SHA1 = ecdsa_plain_signatures.branch("1"); + + /* 0.4.0.127.0.7.1.1.4.1.2 */ + static final ASN1ObjectIdentifier ecdsa_plain_SHA224 = ecdsa_plain_signatures.branch("2"); + + /* 0.4.0.127.0.7.1.1.4.1.3 */ + static final ASN1ObjectIdentifier ecdsa_plain_SHA256 = ecdsa_plain_signatures.branch("3"); + + /* 0.4.0.127.0.7.1.1.4.1.4 */ + static final ASN1ObjectIdentifier ecdsa_plain_SHA384 = ecdsa_plain_signatures.branch("4"); + + /* 0.4.0.127.0.7.1.1.4.1.5 */ + static final ASN1ObjectIdentifier ecdsa_plain_SHA512 = ecdsa_plain_signatures.branch("5"); + + /* 0.4.0.127.0.7.1.1.4.1.6 */ + static final ASN1ObjectIdentifier ecdsa_plain_RIPEMD160 = ecdsa_plain_signatures.branch("6"); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java index 69687e4f1..afcd77678 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeader.java @@ -4,13 +4,13 @@ import java.util.Enumeration; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; import org.spongycastle.asn1.x500.X500Name; @@ -31,7 +31,7 @@ public class PKIHeader private ASN1Integer pvno; private GeneralName sender; private GeneralName recipient; - private DERGeneralizedTime messageTime; + private ASN1GeneralizedTime messageTime; private AlgorithmIdentifier protectionAlg; private ASN1OctetString senderKID; // KeyIdentifier private ASN1OctetString recipKID; // KeyIdentifier @@ -56,7 +56,7 @@ public class PKIHeader switch (tObj.getTagNo()) { case 0: - messageTime = DERGeneralizedTime.getInstance(tObj, true); + messageTime = ASN1GeneralizedTime.getInstance(tObj, true); break; case 1: protectionAlg = AlgorithmIdentifier.getInstance(tObj, true); @@ -136,7 +136,7 @@ public class PKIHeader return recipient; } - public DERGeneralizedTime getMessageTime() + public ASN1GeneralizedTime getMessageTime() { return messageTime; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java index 6532d91f8..5249c5e0e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cmp/PKIHeaderBuilder.java @@ -6,7 +6,6 @@ import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; @@ -46,16 +45,6 @@ public class PKIHeaderBuilder this.recipient = recipient; } - /** - * @deprecated use ASN1GeneralizedTime - */ - public PKIHeaderBuilder setMessageTime(DERGeneralizedTime time) - { - messageTime = ASN1GeneralizedTime.getInstance(time); - - return this; - } - public PKIHeaderBuilder setMessageTime(ASN1GeneralizedTime time) { messageTime = time; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java index 292303a03..59b8772c5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Attribute.java @@ -7,7 +7,6 @@ import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; /** @@ -73,17 +72,6 @@ public class Attribute attrValues = (ASN1Set)seq.getObjectAt(1); } - /** - * @deprecated use ASN1ObjectIdentifier - */ - public Attribute( - DERObjectIdentifier attrType, - ASN1Set attrValues) - { - this.attrType = new ASN1ObjectIdentifier(attrType.getId()); - this.attrValues = attrValues; - } - public Attribute( ASN1ObjectIdentifier attrType, ASN1Set attrValues) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java index 80e71e233..69e0988d4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/AttributeTable.java @@ -8,7 +8,6 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Set; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSet; /** @@ -90,14 +89,6 @@ public class AttributeTable } } - /** - * @deprecated use ASN1ObjectIdentifier - */ - public Attribute get(DERObjectIdentifier oid) - { - return get(new ASN1ObjectIdentifier(oid.getId())); - } - /** * Return the first attribute matching the OBJECT IDENTIFIER oid. * @@ -117,14 +108,6 @@ public class AttributeTable return (Attribute)value; } - /** - * @deprecated use ASN1ObjectIdentifier - */ - public ASN1EncodableVector getAll(DERObjectIdentifier oid) - { - return getAll(new ASN1ObjectIdentifier(oid.getId())); - } - /** * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be * empty if there are no attributes of the required type present. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java index 92377c41b..16d9312fb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/RecipientKeyIdentifier.java @@ -1,12 +1,12 @@ package org.spongycastle.asn1.cms; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSequence; @@ -28,12 +28,12 @@ public class RecipientKeyIdentifier extends ASN1Object { private ASN1OctetString subjectKeyIdentifier; - private DERGeneralizedTime date; + private ASN1GeneralizedTime date; private OtherKeyAttribute other; public RecipientKeyIdentifier( ASN1OctetString subjectKeyIdentifier, - DERGeneralizedTime date, + ASN1GeneralizedTime date, OtherKeyAttribute other) { this.subjectKeyIdentifier = subjectKeyIdentifier; @@ -43,7 +43,7 @@ public class RecipientKeyIdentifier public RecipientKeyIdentifier( byte[] subjectKeyIdentifier, - DERGeneralizedTime date, + ASN1GeneralizedTime date, OtherKeyAttribute other) { this.subjectKeyIdentifier = new DEROctetString(subjectKeyIdentifier); @@ -71,9 +71,9 @@ public class RecipientKeyIdentifier case 1: break; case 2: - if (seq.getObjectAt(1) instanceof DERGeneralizedTime) + if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime) { - date = (DERGeneralizedTime)seq.getObjectAt(1); + date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1)); } else { @@ -81,7 +81,7 @@ public class RecipientKeyIdentifier } break; case 3: - date = (DERGeneralizedTime)seq.getObjectAt(1); + date = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1)); other = OtherKeyAttribute.getInstance(seq.getObjectAt(2)); break; default: @@ -136,7 +136,7 @@ public class RecipientKeyIdentifier return subjectKeyIdentifier; } - public DERGeneralizedTime getDate() + public ASN1GeneralizedTime getDate() { return date; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Time.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Time.java index 44ce16c26..1dccff365 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Time.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cms/Time.java @@ -3,12 +3,15 @@ package org.spongycastle.asn1.cms; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.SimpleTimeZone; import org.spongycastle.asn1.ASN1Choice; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1TaggedObject; +import org.spongycastle.asn1.ASN1UTCTime; import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERUTCTime; @@ -47,8 +50,8 @@ public class Time public Time( ASN1Primitive time) { - if (!(time instanceof DERUTCTime) - && !(time instanceof DERGeneralizedTime)) + if (!(time instanceof ASN1UTCTime) + && !(time instanceof ASN1GeneralizedTime)) { throw new IllegalArgumentException("unknown object passed to Time"); } @@ -57,28 +60,61 @@ public class Time } /** - * Create a time object from a given date - if the year is in between 1950 + * Creates a time object from a given date - if the date is between 1950 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime * is used. + * + * @param time a date object representing the time of interest. */ public Time( - Date date) + Date time) { SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss"); dateF.setTimeZone(tz); - String d = dateF.format(date) + "Z"; + String d = dateF.format(time) + "Z"; int year = Integer.parseInt(d.substring(0, 4)); if (year < 1950 || year > 2049) { - time = new DERGeneralizedTime(d); + this.time = new DERGeneralizedTime(d); } else { - time = new DERUTCTime(d.substring(2)); + this.time = new DERUTCTime(d.substring(2)); + } + } + + /** + * Creates a time object from a given date and locale - if the date is between 1950 + * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime + * is used. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. + * + * @param time a date object representing the time of interest. + * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value. + */ + public Time( + Date time, + Locale locale) + { + SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); + SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale); + + dateF.setTimeZone(tz); + + String d = dateF.format(time) + "Z"; + int year = Integer.parseInt(d.substring(0, 4)); + + if (year < 1950 || year > 2049) + { + this.time = new DERGeneralizedTime(d); + } + else + { + this.time = new DERUTCTime(d.substring(2)); } } @@ -103,13 +139,13 @@ public class Time { return (Time)obj; } - else if (obj instanceof DERUTCTime) + else if (obj instanceof ASN1UTCTime) { - return new Time((DERUTCTime)obj); + return new Time((ASN1UTCTime)obj); } - else if (obj instanceof DERGeneralizedTime) + else if (obj instanceof ASN1GeneralizedTime) { - return new Time((DERGeneralizedTime)obj); + return new Time((ASN1GeneralizedTime)obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName()); @@ -120,13 +156,13 @@ public class Time */ public String getTime() { - if (time instanceof DERUTCTime) + if (time instanceof ASN1UTCTime) { - return ((DERUTCTime)time).getAdjustedTime(); + return ((ASN1UTCTime)time).getAdjustedTime(); } else { - return ((DERGeneralizedTime)time).getTime(); + return ((ASN1GeneralizedTime)time).getTime(); } } @@ -137,13 +173,13 @@ public class Time { try { - if (time instanceof DERUTCTime) + if (time instanceof ASN1UTCTime) { - return ((DERUTCTime)time).getAdjustedDate(); + return ((ASN1UTCTime)time).getAdjustedDate(); } else { - return ((DERGeneralizedTime)time).getDate(); + return ((ASN1GeneralizedTime)time).getDate(); } } catch (ParseException e) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java index 5260675e1..db64c138b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/cryptopro/ECGOST3410NamedCurves.java @@ -6,8 +6,8 @@ import java.util.Hashtable; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.math.ec.ECConstants; import org.spongycastle.math.ec.ECCurve; -import org.spongycastle.math.ec.ECPoint; /** * table of the available named parameters for GOST 3410-2001. @@ -26,7 +26,9 @@ public class ECGOST3410NamedCurves ECCurve.Fp curve = new ECCurve.Fp( mod_p, // p new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a - new BigInteger("166")); // b + new BigInteger("166"), // b + mod_q, + ECConstants.ONE); ECDomainParameters ecParams = new ECDomainParameters( curve, @@ -43,7 +45,9 @@ public class ECGOST3410NamedCurves curve = new ECCurve.Fp( mod_p, // p new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), - new BigInteger("166")); + new BigInteger("166"), + mod_q, + ECConstants.ONE); ecParams = new ECDomainParameters( curve, @@ -60,7 +64,9 @@ public class ECGOST3410NamedCurves curve = new ECCurve.Fp( mod_p, // p new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a - new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595")); // b + new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b + mod_q, + ECConstants.ONE); ecParams = new ECDomainParameters( curve, @@ -77,7 +83,9 @@ public class ECGOST3410NamedCurves curve = new ECCurve.Fp( mod_p, // p new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), - new BigInteger("32858")); + new BigInteger("32858"), + mod_q, + ECConstants.ONE); ecParams = new ECDomainParameters( curve, @@ -93,7 +101,9 @@ public class ECGOST3410NamedCurves curve = new ECCurve.Fp( mod_p, // p new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a - new BigInteger("32858")); // b + new BigInteger("32858"), // b + mod_q, + ECConstants.ONE); ecParams = new ECDomainParameters( curve, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java index 1c6f5b80b..63e02d4e2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CVCertificate.java @@ -15,7 +15,6 @@ import org.spongycastle.asn1.DEROctetString; /** * an iso7816Certificate structure. - *
** Certificate ::= SEQUENCE { * CertificateBody Iso7816CertificateBody, @@ -85,7 +84,6 @@ public class CVCertificate * Create an iso7816Certificate structure from an ASN1InputStream. * * @param aIS the byte stream to parse. - * @return the Iso7816CertificateStructure represented by the byte stream. * @throws IOException if there is a problem parsing the data. */ public CVCertificate(ASN1InputStream aIS) @@ -129,7 +127,6 @@ public class CVCertificate * * @param body the Iso7816CertificateBody object containing the body. * @param signature the byte array containing the signature - * @return the Iso7816CertificateStructure * @throws IOException if there is a problem parsing the data. */ public CVCertificate(CertificateBody body, byte[] signature) @@ -147,7 +144,6 @@ public class CVCertificate * * @param obj the Object to extract the certificate from. * @return the Iso7816CertificateStructure represented by the byte stream. - * @throws IOException if there is a problem parsing the data. */ public static CVCertificate getInstance(Object obj) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java index 3c834fdc0..a64ec682a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateBody.java @@ -13,7 +13,6 @@ import org.spongycastle.asn1.DEROctetString; /** * an Iso7816CertificateBody structure. - * ** CertificateBody ::= SEQUENCE { * // version of the certificate format. Must be 0 (version 1) @@ -128,7 +127,6 @@ public class CertificateBody * @param certificateHolderAuthorization * @param certificateEffectiveDate * @param certificateExpirationDate - * @throws IOException */ public CertificateBody( DERApplicationSpecific certificateProfileIdentifier, @@ -276,7 +274,6 @@ public class CertificateBody * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets. * * @return return the ASN1Primitive representing the "request" or "profile" type certificate body. - * @throws IOException if the DERApplicationSpecific cannot be created or if data are missings to create a valid certificate. */ public ASN1Primitive toASN1Primitive() { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java index 5f23f973f..b70b181ff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/CertificateHolderAuthorization.java @@ -13,7 +13,6 @@ import org.spongycastle.util.Integers; /** * an Iso7816CertificateHolderAuthorization structure. - * ** Certificate Holder Authorization ::= SEQUENCE { * // specifies the format and the rules for the evaluation of the authorization diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java index 2c76e1ecd..94e8b21c5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/EACObjectIdentifiers.java @@ -4,17 +4,17 @@ import org.spongycastle.asn1.ASN1ObjectIdentifier; /** * German Federal Office for Information Security - * (Bundesamt für Sicherheit in der Informationstechnik) + * (Bundesamt für Sicherheit in der Informationstechnik) * http://www.bsi.bund.de/ ** BSI TR-03110 * Technical Guideline Advanced Security Mechanisms for Machine Readable Travel Documents *
- * Technical Guideline TR-03110-3 + * + * Technical Guideline TR-03110-3 * Advanced Security Mechanisms for Machine Readable Travel Documents; * Part 3: Common Specifications. */ - public interface EACObjectIdentifiers { /** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java index 376dcfa89..c241de2de 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/ECDSAPublicKey.java @@ -15,7 +15,6 @@ import org.spongycastle.asn1.DERTaggedObject; /** * an Iso7816ECDSAPublicKeyStructure structure. - *
** Certificate Holder Authorization ::= SEQUENCE { * ASN1TaggedObject primeModulusP; // OPTIONAL diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java index 0726a72e0..bdb02271d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/PackedDate.java @@ -3,6 +3,7 @@ package org.spongycastle.asn1.eac; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.SimpleTimeZone; import org.spongycastle.util.Arrays; @@ -21,7 +22,9 @@ public class PackedDate } /** - * base constructer from a java.util.date object + * Base constructor from a java.util.date object. + * + * @param time a date object representing the time of interest. */ public PackedDate( Date time) @@ -33,6 +36,24 @@ public class PackedDate this.time = convert(dateF.format(time)); } + /** + * Base constructor from a java.util.date object. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the PackedDate produced is compatible with other ASN.1 implementations. + * + * @param time a date object representing the time of interest. + * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value. + */ + public PackedDate( + Date time, + Locale locale) + { + SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'", locale); + + dateF.setTimeZone(new SimpleTimeZone(0,"Z")); + + this.time = convert(dateF.format(time)); + } + private byte[] convert(String sTime) { char[] digs = sTime.toCharArray(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java index 2061a188c..6142c645a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/eac/RSAPublicKey.java @@ -12,7 +12,6 @@ import org.spongycastle.asn1.DERSequence; /** * an Iso7816RSAPublicKeyStructure structure. - * ** Certificate Holder Authorization ::= SEQUENCE { * // modulus should be at least 1024bit and a multiple of 512. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java index d544c937b..aebb16e8b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ess/ContentHints.java @@ -6,7 +6,6 @@ import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERUTF8String; @@ -47,25 +46,6 @@ public class ContentHints } } - /** - * @deprecated use ASN1ObjectIdentifier - */ - public ContentHints( - DERObjectIdentifier contentType) - { - this(new ASN1ObjectIdentifier(contentType.getId())); - } - - /** - * @deprecated use ASN1ObjectIdentifier - */ - public ContentHints( - DERObjectIdentifier contentType, - DERUTF8String contentDescription) - { - this(new ASN1ObjectIdentifier(contentType.getId()), contentDescription); - } - public ContentHints( ASN1ObjectIdentifier contentType) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java index cb0fa3b03..4ad1300c9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/icao/CscaMasterList.java @@ -13,7 +13,7 @@ import org.spongycastle.asn1.x509.Certificate; /** * The CscaMasterList object. This object can be wrapped in a * CMSSignedData to be published in LDAP. - * + * ** CscaMasterList ::= SEQUENCE { * version CscaMasterListVersion, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java index 85dc7f329..83a856957 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/CertHash.java @@ -19,8 +19,6 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; * the expiry of the corresponding certificate. Hence, clients MUST support this * extension. If a positive statement of availability is to be delivered, this * extension syntax and OID MUST be used. - * - * ** CertHash ::= SEQUENCE { * hashAlgorithm AlgorithmIdentifier, @@ -102,9 +100,8 @@ public class CertHash /** * Produce an object suitable for an ASN1OutputStream. - * + ** Returns: - *
** CertHash ::= SEQUENCE { * hashAlgorithm AlgorithmIdentifier, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java index 395c37439..c00e3721a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/ocsp/RequestedCertificate.java @@ -16,7 +16,7 @@ import org.spongycastle.asn1.x509.Certificate; * ISIS-MTT-Optional: The certificate requested by the client by inserting the * RetrieveIfAllowed extension in the request, will be returned in this * extension. - * + ** ISIS-MTT-SigG: The signature act allows publishing certificates only then, * when the certificate owner gives his explicit permission. Accordingly, there * may be �nondownloadable� certificates, about which the responder must provide @@ -36,7 +36,6 @@ import org.spongycastle.asn1.x509.Certificate; * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If * any of the OCTET STRING options is used, it MUST contain the DER encoding of * the requested certificate. - *
** RequestedCertificate ::= CHOICE { * Certificate Certificate, @@ -105,7 +104,7 @@ public class RequestedCertificate /** * Constructor from a given details. - * + ** Only one parameter can be given. All other must be
+ *null
. * * @param certificate Given as Certificate @@ -155,9 +154,8 @@ public class RequestedCertificate /** * Produce an object suitable for an ASN1OutputStream. - ** Returns: - *
** RequestedCertificate ::= CHOICE { * Certificate Certificate, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java index 8436b9d2f..948f5ba46 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java @@ -54,9 +54,8 @@ public class AdditionalInformationSyntax /** * Produce an object suitable for an ASN1OutputStream. - * + ** Returns: - *
** AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048)) *diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java index 1cc5f4071..bc4a667fb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/AdmissionSyntax.java @@ -11,28 +11,28 @@ import org.spongycastle.asn1.x509.GeneralName; /** * Attribute to indicate admissions to certain professions. - * + * ** AdmissionSyntax ::= SEQUENCE * { * admissionAuthority GeneralName OPTIONAL, * contentsOfAdmissions SEQUENCE OF Admissions * } - * + * * Admissions ::= SEQUENCE * { * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL * professionInfos SEQUENCE OF ProfessionInfo * } - * + * * NamingAuthority ::= SEQUENCE * { * namingAuthorityId OBJECT IDENTIFIER OPTIONAL, * namingAuthorityUrl IA5String OPTIONAL, * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL * } - * + * * ProfessionInfo ::= SEQUENCE * { * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL, @@ -42,8 +42,7 @@ import org.spongycastle.asn1.x509.GeneralName; * addProfessionInfo OCTET STRING OPTIONAL * } *- * - * + ** ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax * supports the following concepts and requirements: *
* By means of different namingAuthority-OIDs or profession OIDs hierarchies of * professions, specializations, disciplines, fields of activity, etc. can be * expressed. The issuing admission authority should always be indicated (field @@ -89,9 +88,7 @@ import org.spongycastle.asn1.x509.GeneralName; * naming authority by the exclusive use of the component professionItems. In * this case the certification authority is responsible for the verification of * the admission information. - *
- * - * + ** This attribute is single-valued. Still, several admissions can be captured in * the sequence structure of the component contentsOfAdmissions of * AdmissionSyntax or in the component professionInfos of Admissions. The @@ -102,7 +99,7 @@ import org.spongycastle.asn1.x509.GeneralName; * value for the component namingAuthority of ProfessionInfo. Within the latter * component the default value can be overwritten, in case that another naming * authority needs to be recorded. - *
+ ** The length of the string objects is limited to 128 characters. It is * recommended to indicate a namingAuthorityURL in all issued attribute * certificates. If a namingAuthorityURL is indicated, the field professionItems @@ -209,30 +206,29 @@ public class AdmissionSyntax /** * Produce an object suitable for an ASN1OutputStream. - *
+ ** Returns: - *
** AdmissionSyntax ::= SEQUENCE * { * admissionAuthority GeneralName OPTIONAL, * contentsOfAdmissions SEQUENCE OF Admissions * } - * + * * Admissions ::= SEQUENCE * { * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL * professionInfos SEQUENCE OF ProfessionInfo * } - * + * * NamingAuthority ::= SEQUENCE * { * namingAuthorityId OBJECT IDENTIFIER OPTIONAL, * namingAuthorityUrl IA5String OPTIONAL, * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL * } - * + * * ProfessionInfo ::= SEQUENCE * { * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java index 9b140c966..db0cefa3c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Admissions.java @@ -14,7 +14,6 @@ import org.spongycastle.asn1.x509.GeneralName; /** * An Admissions structure. - * ** Admissions ::= SEQUENCE * { @@ -22,7 +21,6 @@ import org.spongycastle.asn1.x509.GeneralName; * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL * professionInfos SEQUENCE OF ProfessionInfo * } - * ** * @see org.spongycastle.asn1.isismtt.x509.AdmissionSyntax @@ -117,7 +115,7 @@ public class Admissions /** * Constructor from a given details. - * + ** Parameter
+ *professionInfos
is mandatory. * * @param admissionAuthority The admission authority. @@ -155,9 +153,8 @@ public class Admissions /** * Produce an object suitable for an ASN1OutputStream. - ** Returns: - *
** Admissions ::= SEQUENCE * { @@ -165,7 +162,6 @@ public class Admissions * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL * professionInfos SEQUENCE OF ProfessionInfo * } - * ** * @return an ASN1Primitive diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java index fa8851d76..900f4c08f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/DeclarationOfMajority.java @@ -15,7 +15,7 @@ import org.spongycastle.asn1.DERTaggedObject; /** * A declaration of majority. - * + * ** DeclarationOfMajoritySyntax ::= CHOICE * { @@ -28,7 +28,7 @@ import org.spongycastle.asn1.DERTaggedObject; * dateOfBirth [2] IMPLICIT GeneralizedTime * } *- * + ** fullAgeAtCountry indicates the majority of the owner with respect to the laws * of a specific country. */ @@ -101,9 +101,8 @@ public class DeclarationOfMajority /** * Produce an object suitable for an ASN1OutputStream. - *
+ ** Returns: - *
** DeclarationOfMajoritySyntax ::= CHOICE * { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java index f7f646d20..71f08dd16 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/MonetaryLimit.java @@ -17,11 +17,10 @@ import org.spongycastle.asn1.DERSequence; * since January 1, 2004. For the sake of backward compatibility with * certificates already in use, components SHOULD support MonetaryLimit (as well * as QcEuLimitValue). - * + ** Indicates a monetary limit within which the certificate holder is authorized * to act. (This value DOES NOT express a limit on the liability of the * certification authority). - *
** MonetaryLimitSyntax ::= SEQUENCE * { @@ -30,9 +29,9 @@ import org.spongycastle.asn1.DERSequence; * exponent INTEGER * } *- * + ** currency must be the ISO code. - *
+ ** value = amount�10*exponent */ public class MonetaryLimit @@ -72,8 +71,7 @@ public class MonetaryLimit /** * Constructor from a given details. - *
- * + ** value = amount�10^exponent * * @param currency The currency. Must be the ISO code. @@ -104,9 +102,8 @@ public class MonetaryLimit /** * Produce an object suitable for an ASN1OutputStream. - *
+ ** Returns: - *
** MonetaryLimitSyntax ::= SEQUENCE * { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java index 920d2e0d1..944a0c319 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/NamingAuthority.java @@ -11,7 +11,6 @@ import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1String; import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.isismtt.ISISMTTObjectIdentifiers; import org.spongycastle.asn1.x500.DirectoryString; @@ -173,27 +172,9 @@ public class NamingAuthority return namingAuthorityUrl; } - /** - * Constructor from given details. - * - * All parameters can be combined. - * - * @param namingAuthorityId ObjectIdentifier for naming authority. - * @param namingAuthorityUrl URL for naming authority. - * @param namingAuthorityText Textual representation of naming authority. - * @deprecated use ASN1ObjectIdentifier method - */ - public NamingAuthority(DERObjectIdentifier namingAuthorityId, - String namingAuthorityUrl, DirectoryString namingAuthorityText) - { - this.namingAuthorityId = new ASN1ObjectIdentifier(namingAuthorityId.getId()); - this.namingAuthorityUrl = namingAuthorityUrl; - this.namingAuthorityText = namingAuthorityText; - } - /** * Constructor from given details. - * + ** All parameters can be combined. * * @param namingAuthorityId ObjectIdentifier for naming authority. @@ -210,9 +191,8 @@ public class NamingAuthority /** * Produce an object suitable for an ASN1OutputStream. - *
+ ** Returns: - *
** NamingAuthority ::= SEQUENCE * { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java index 5838fee30..5e4ecca50 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProcurationSyntax.java @@ -132,8 +132,7 @@ public class ProcurationSyntax /** * Constructor from a given details. - * - * + *- * + * @deprecated create the extension using org.spongycastle.cert.X509ExtensionUtils **/ public AuthorityKeyIdentifier( SubjectPublicKeyInfo spki) @@ -118,6 +118,7 @@ public class AuthorityKeyIdentifier /** * create an AuthorityKeyIdentifier with the GeneralNames tag and * the serial number provided as well. + * @deprecated create the extension using org.spongycastle.cert.X509ExtensionUtils */ public AuthorityKeyIdentifier( SubjectPublicKeyInfo spki, @@ -144,9 +145,7 @@ public class AuthorityKeyIdentifier GeneralNames name, BigInteger serialNumber) { - this.keyidentifier = null; - this.certissuer = GeneralNames.getInstance(name.toASN1Primitive()); - this.certserno = new ASN1Integer(serialNumber); + this((byte[])null, name, serialNumber); } /** @@ -155,9 +154,7 @@ public class AuthorityKeyIdentifier public AuthorityKeyIdentifier( byte[] keyIdentifier) { - this.keyidentifier = new DEROctetString(keyIdentifier); - this.certissuer = null; - this.certserno = null; + this(keyIdentifier, null, null); } /** @@ -169,9 +166,9 @@ public class AuthorityKeyIdentifier GeneralNames name, BigInteger serialNumber) { - this.keyidentifier = new DEROctetString(keyIdentifier); - this.certissuer = GeneralNames.getInstance(name.toASN1Primitive()); - this.certserno = new ASN1Integer(serialNumber); + this.keyidentifier = (keyIdentifier != null) ? new DEROctetString(keyIdentifier) : null; + this.certissuer = name; + this.certserno = (serialNumber != null) ? new ASN1Integer(serialNumber) : null; } public byte[] getKeyIdentifier() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java index f7ad39be4..32f81cc91 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/BasicConstraints.java @@ -9,7 +9,6 @@ import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERBoolean; import org.spongycastle.asn1.DERSequence; public class BasicConstraints @@ -59,9 +58,9 @@ public class BasicConstraints } else { - if (seq.getObjectAt(0) instanceof DERBoolean) + if (seq.getObjectAt(0) instanceof ASN1Boolean) { - this.cA = DERBoolean.getInstance(seq.getObjectAt(0)); + this.cA = ASN1Boolean.getInstance(seq.getObjectAt(0)); } else { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java index 91465bb5d..976473fd5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/CertificatePair.java @@ -123,9 +123,8 @@ public class CertificatePair /** * Produce an object suitable for an ASN1OutputStream. - * + ** Either
- * + *generalName
orcertRef
MUST be *null
. * @@ -154,8 +153,7 @@ public class ProcurationSyntax /** * Constructor from a given details. - ** Either
+ *generalName
orcertRef
MUST be *null
. * @@ -196,16 +194,15 @@ public class ProcurationSyntax /** * Produce an object suitable for an ASN1OutputStream. - ** Returns: - *
** ProcurationSyntax ::= SEQUENCE { * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL, * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL, * signingFor [3] EXPLICIT SigningFor * } - * + * * SigningFor ::= CHOICE * { * thirdPerson GeneralName, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java index cf91505ed..79b2b5255 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/ProfessionInfo.java @@ -274,7 +274,7 @@ public class ProfessionInfo /** * Constructor from given details. - * + **/ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java index caaa7b326..47bdaaff5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/EncryptionScheme.java @@ -25,7 +25,7 @@ public class EncryptionScheme this.algId = AlgorithmIdentifier.getInstance(seq); } - public static final EncryptionScheme getInstance(Object obj) + public static EncryptionScheme getInstance(Object obj) { if (obj instanceof EncryptionScheme) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java index c6240bd01..9b9c72b5c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/KeyDerivationFunc.java @@ -25,7 +25,7 @@ public class KeyDerivationFunc this.algId = AlgorithmIdentifier.getInstance(seq); } - public static final KeyDerivationFunc getInstance(Object obj) + public static KeyDerivationFunc getInstance(Object obj) { if (obj instanceof KeyDerivationFunc) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java index 40dd191fc..323b02b15 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/PrivateKeyInfo.java @@ -68,7 +68,7 @@ public class PrivateKeyInfo } /** - * @deprectaed use PrivateKeyInfo.getInstance() + * @deprecated use PrivateKeyInfo.getInstance() * @param seq */ public PrivateKeyInfo( diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java index 1114d8c12..f33732a94 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/sec/SECNamedCurves.java @@ -10,6 +10,8 @@ import org.spongycastle.asn1.x9.X9ECParametersHolder; import org.spongycastle.math.ec.ECConstants; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.endo.GLVTypeBEndomorphism; +import org.spongycastle.math.ec.endo.GLVTypeBParameters; import org.spongycastle.util.Strings; import org.spongycastle.util.encoders.Hex; @@ -17,19 +19,14 @@ public class SECNamedCurves { private static ECCurve configureCurve(ECCurve curve) { -// int coord = ECCurve.COORD_JACOBIAN_MODIFIED; -// -// if (curve.getCoordinateSystem() != coord && curve.supportsCoordinateSystem(coord)) -// { -// return curve.configure() -// .setCoordinateSystem(coord) -//// .setMultiplier(new WNafL2RMultiplier()) -// .create(); -// } - return curve; } + private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p) + { + return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create(); + } + private static BigInteger fromHex( String hex) { @@ -51,7 +48,7 @@ public class SECNamedCurves BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "09487239995A5EE76B55F9C2F098")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -77,7 +74,7 @@ public class SECNamedCurves BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B"); BigInteger h = BigInteger.valueOf(4); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "4BA30AB5E892B4E1649DD0928643")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -103,7 +100,7 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "161FF7528B899B2D0C28607CA52C5B86")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -129,7 +126,7 @@ public class SECNamedCurves BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3"); BigInteger h = BigInteger.valueOf(4); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "7B6AA5D85E572983E6FB32A7CDEBC140")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -155,7 +152,20 @@ public class SECNamedCurves BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16), + new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16), + new BigInteger[]{ + new BigInteger("9162fbe73984472a0a9e", 16), + new BigInteger("-96341f1138933bc2f505", 16) }, + new BigInteger[]{ + new BigInteger("127971af8721782ecffa3", 16), + new BigInteger("9162fbe73984472a0a9e", 16) }, + new BigInteger("9162fbe73984472a0a9d0590", 16), + new BigInteger("96341f1138933bc2f503fd44", 16), + 176); + + ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); // ECPoint G = curve.decodePoint(Hex.decode("02" // + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -181,7 +191,7 @@ public class SECNamedCurves BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "4A96B5688EF573284664698968C38BB913CBFC82")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -207,7 +217,7 @@ public class SECNamedCurves BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -233,7 +243,20 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16), + new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16), + new BigInteger[]{ + new BigInteger("71169be7330b3038edb025f1", 16), + new BigInteger("-b3fb3400dec5c4adceb8655c", 16) }, + new BigInteger[]{ + new BigInteger("12511cfe811d0f4e6bc688b4d", 16), + new BigInteger("71169be7330b3038edb025f1", 16) }, + new BigInteger("71169be7330b3038edb025f1d0f9", 16), + new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16), + 208); + + ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -259,7 +282,7 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -285,7 +308,20 @@ public class SECNamedCurves BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16), + new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16), + new BigInteger[]{ + new BigInteger("6b8cf07d4ca75c88957d9d670591", 16), + new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) }, + new BigInteger[]{ + new BigInteger("1243ae1b4d71613bc9f780a03690e", 16), + new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) }, + new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16), + new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16), + 240); + + ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -311,7 +347,7 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -337,7 +373,20 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16), + new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16), + new BigInteger[]{ + new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16), + new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) }, + new BigInteger[]{ + new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16), + new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) }, + new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16), + new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16), + 272); + + ECCurve curve = configureCurveGLV(new ECCurve.Fp(p, a, b, n, h), glv); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -363,7 +412,7 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -389,7 +438,7 @@ public class SECNamedCurves BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("03" //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7")); ECPoint G = curve.decodePoint(Hex.decode("04" @@ -415,7 +464,7 @@ public class SECNamedCurves BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"); BigInteger h = BigInteger.valueOf(1); - ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b)); + ECCurve curve = configureCurve(new ECCurve.Fp(p, a, b, n, h)); //ECPoint G = curve.decodePoint(Hex.decode("02" //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java index 7ea7c6e53..003a3640a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTNamedCurves.java @@ -26,16 +26,19 @@ public class TeleTrusTNamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a - new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16))); // b + new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G - new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; @@ -43,17 +46,20 @@ public class TeleTrusTNamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( // new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a' - new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16))); // b' + new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G - new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; @@ -61,16 +67,19 @@ public class TeleTrusTNamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a - new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16))); // b + new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G - new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; @@ -78,17 +87,20 @@ public class TeleTrusTNamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a' - new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16))); // b' + new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G' - new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; @@ -96,165 +108,195 @@ public class TeleTrusTNamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a - new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16))); // b + new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G - new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n - new BigInteger("01", 16)); // n + n, h); } }; static X9ECParametersHolder brainpoolP224t1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a' - new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16))); // b' + new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G' - new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP256r1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a - new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16))); // b + new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G - new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP256t1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a' - new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16))); // b' + new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G' - new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP320r1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a - new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16))); // b + new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G - new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP320t1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a' - new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16))); // b' + new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G' - new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP384r1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a - new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16))); // b + new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G - new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP384t1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a' - new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16))); // b' + new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G' - new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP512r1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a - new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16))); // b + new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16), // b + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G - new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; static X9ECParametersHolder brainpoolP512t1 = new X9ECParametersHolder() { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16); + BigInteger h = new BigInteger("01", 16); + ECCurve curve = configureCurve(new ECCurve.Fp( //new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a' - new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16))); // b' + new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16), // b' + n, h)); return new X9ECParameters( curve, curve.decodePoint(Hex.decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G' - new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n - new BigInteger("01", 16)); // h + n, h); } }; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java index 32433a153..1876000ef 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java @@ -41,35 +41,35 @@ public interface TeleTrusTObjectIdentifiers static final ASN1ObjectIdentifier ecc_brainpool = teleTrusTAlgorithm.branch("3.2.8"); /** 1.3.36.3.3.2.8.1 */ static final ASN1ObjectIdentifier ellipticCurve = ecc_brainpool.branch("1"); - /** 1.3.36.3.3.2.8.1 */ + /** 1.3.36.3.3.2.8.1.1 */ static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1"); - /** 1.3.36.3.3.2.8.1.1 */ + /** 1.3.36.3.3.2.8.1.1.1 */ static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1"); - /** 1.3.36.3.3.2.8.1.2 */ + /** 1.3.36.3.3.2.8.1.1.2 */ static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2"); - /** 1.3.36.3.3.2.8.1.3 */ + /** 1.3.36.3.3.2.8.1.1.3 */ static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3"); - /** 1.3.36.3.3.2.8.1.4 */ + /** 1.3.36.3.3.2.8.1.1.4 */ static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4"); - /** 1.3.36.3.3.2.8.1.5 */ + /** 1.3.36.3.3.2.8.1.1.5 */ static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5"); - /** 1.3.36.3.3.2.8.1.6 */ + /** 1.3.36.3.3.2.8.1.1.6 */ static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6"); - /** 1.3.36.3.3.2.8.1.7 */ + /** 1.3.36.3.3.2.8.1.1.7 */ static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7"); - /** 1.3.36.3.3.2.8.1.8 */ + /** 1.3.36.3.3.2.8.1.1.8 */ static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8"); - /** 1.3.36.3.3.2.8.1.9 */ + /** 1.3.36.3.3.2.8.1.1.9 */ static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9"); - /** 1.3.36.3.3.2.8.1.10 */ + /** 1.3.36.3.3.2.8.1.1.10 */ static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10"); - /** 1.3.36.3.3.2.8.1.11 */ + /** 1.3.36.3.3.2.8.1.1.11 */ static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11"); - /** 1.3.36.3.3.2.8.1.12 */ + /** 1.3.36.3.3.2.8.1.1.12 */ static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12"); - /** 1.3.36.3.3.2.8.1.13 */ + /** 1.3.36.3.3.2.8.1.1.13 */ static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13"); - /** 1.3.36.3.3.2.8.1.14 */ + /** 1.3.36.3.3.2.8.1.1.14 */ static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14"); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java index 945984745..bd2d9add5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145ECBinary.java @@ -12,15 +12,15 @@ import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; -import org.spongycastle.asn1.x9.X9IntegerConverter; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.field.PolynomialExtensionField; import org.spongycastle.util.Arrays; public class DSTU4145ECBinary extends ASN1Object { - BigInteger version = BigInteger.valueOf(0); DSTU4145BinaryField f; @@ -31,17 +31,27 @@ public class DSTU4145ECBinary public DSTU4145ECBinary(ECDomainParameters params) { - if (!(params.getCurve() instanceof ECCurve.F2m)) + ECCurve curve = params.getCurve(); + if (!ECAlgorithms.isF2mCurve(curve)) { throw new IllegalArgumentException("only binary domain is possible"); } // We always use big-endian in parameter encoding - ECCurve.F2m curve = (ECCurve.F2m)params.getCurve(); - f = new DSTU4145BinaryField(curve.getM(), curve.getK1(), curve.getK2(), curve.getK3()); + + PolynomialExtensionField field = (PolynomialExtensionField)curve.getField(); + int[] exponents = field.getMinimalPolynomial().getExponentsPresent(); + if (exponents.length == 3) + { + f = new DSTU4145BinaryField(exponents[2], exponents[1]); + } + else if (exponents.length == 5) + { + f = new DSTU4145BinaryField(exponents[4], exponents[1], exponents[2], exponents[3]); + } + a = new ASN1Integer(curve.getA().toBigInteger()); - X9IntegerConverter converter = new X9IntegerConverter(); - b = new DEROctetString(converter.integerToBytes(curve.getB().toBigInteger(), converter.getByteLength(curve))); + b = new DEROctetString(curve.getB().getEncoded()); n = new ASN1Integer(params.getN()); bp = new DEROctetString(DSTU4145PointEncoder.encodePoint(params.getG())); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java index dcde92d4a..252c4404e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145NamedCurves.java @@ -21,17 +21,41 @@ public class DSTU4145NamedCurves static { + BigInteger[] n_s = new BigInteger[10]; + n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16); + n_s[1] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFB12EBCC7D7F29FF7701F", 16); + n_s[2] = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16); + n_s[3] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFB981960435FE5AB64236EF", 16); + n_s[4] = new BigInteger("40000000000000000000000069A779CAC1DABC6788F7474F", 16); + n_s[5] = new BigInteger("1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 16); + n_s[6] = new BigInteger("800000000000000000000000000000006759213AF182E987D3E17714907D470D", 16); + n_s[7] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC079C2F3825DA70D390FBBA588D4604022B7B7", 16); + n_s[8] = new BigInteger("40000000000000000000000000000000000000000000009C300B75A3FA824F22428FD28CE8812245EF44049B2D49", 16); + n_s[9] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16); + + BigInteger[] h_s = new BigInteger[10]; + h_s[0] = BigInteger.valueOf(2); + h_s[1] = BigInteger.valueOf(2); + h_s[2] = BigInteger.valueOf(4); + h_s[3] = BigInteger.valueOf(2); + h_s[4] = BigInteger.valueOf(2); + h_s[5] = BigInteger.valueOf(2); + h_s[6] = BigInteger.valueOf(4); + h_s[7] = BigInteger.valueOf(2); + h_s[8] = BigInteger.valueOf(2); + h_s[9] = BigInteger.valueOf(2); + ECCurve.F2m[] curves = new ECCurve.F2m[10]; - curves[0] = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16)); - curves[1] = new ECCurve.F2m(167, 6, ONE, new BigInteger("6EE3CEEB230811759F20518A0930F1A4315A827DAC", 16)); - curves[2] = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16)); - curves[3] = new ECCurve.F2m(179, 1, 2, 4, ONE, new BigInteger("4A6E0856526436F2F88DD07A341E32D04184572BEB710", 16)); - curves[4] = new ECCurve.F2m(191, 9, ONE, new BigInteger("7BC86E2102902EC4D5890E8B6B4981ff27E0482750FEFC03", 16)); - curves[5] = new ECCurve.F2m(233, 1, 4, 9, ONE, new BigInteger("06973B15095675534C7CF7E64A21BD54EF5DD3B8A0326AA936ECE454D2C", 16)); - curves[6] = new ECCurve.F2m(257, 12, ZERO, new BigInteger("1CEF494720115657E18F938D7A7942394FF9425C1458C57861F9EEA6ADBE3BE10", 16)); - curves[7] = new ECCurve.F2m(307, 2, 4, 8, ONE, new BigInteger("393C7F7D53666B5054B5E6C6D3DE94F4296C0C599E2E2E241050DF18B6090BDC90186904968BB", 16)); - curves[8] = new ECCurve.F2m(367, 21, ONE, new BigInteger("43FC8AD242B0B7A6F3D1627AD5654447556B47BF6AA4A64B0C2AFE42CADAB8F93D92394C79A79755437B56995136", 16)); - curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16)); + curves[0] = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16), n_s[0], h_s[0]); + curves[1] = new ECCurve.F2m(167, 6, ONE, new BigInteger("6EE3CEEB230811759F20518A0930F1A4315A827DAC", 16), n_s[1], h_s[1]); + curves[2] = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16), n_s[2], h_s[2]); + curves[3] = new ECCurve.F2m(179, 1, 2, 4, ONE, new BigInteger("4A6E0856526436F2F88DD07A341E32D04184572BEB710", 16), n_s[3], h_s[3]); + curves[4] = new ECCurve.F2m(191, 9, ONE, new BigInteger("7BC86E2102902EC4D5890E8B6B4981ff27E0482750FEFC03", 16), n_s[4], h_s[4]); + curves[5] = new ECCurve.F2m(233, 1, 4, 9, ONE, new BigInteger("06973B15095675534C7CF7E64A21BD54EF5DD3B8A0326AA936ECE454D2C", 16), n_s[5], h_s[5]); + curves[6] = new ECCurve.F2m(257, 12, ZERO, new BigInteger("1CEF494720115657E18F938D7A7942394FF9425C1458C57861F9EEA6ADBE3BE10", 16), n_s[6], h_s[6]); + curves[7] = new ECCurve.F2m(307, 2, 4, 8, ONE, new BigInteger("393C7F7D53666B5054B5E6C6D3DE94F4296C0C599E2E2E241050DF18B6090BDC90186904968BB", 16), n_s[7], h_s[7]); + curves[8] = new ECCurve.F2m(367, 21, ONE, new BigInteger("43FC8AD242B0B7A6F3D1627AD5654447556B47BF6AA4A64B0C2AFE42CADAB8F93D92394C79A79755437B56995136", 16), n_s[8], h_s[8]); + curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16), n_s[9], h_s[9]); ECPoint[] points = new ECPoint[10]; points[0] = curves[0].createPoint(new BigInteger("2E2F85F5DD74CE983A5C4237229DAF8A3F35823BE", 16), new BigInteger("3826F008A8C51D7B95284D9D03FF0E00CE2CD723A", 16)); @@ -45,21 +69,9 @@ public class DSTU4145NamedCurves points[8] = curves[8].createPoint(new BigInteger("324A6EDDD512F08C49A99AE0D3F961197A76413E7BE81A400CA681E09639B5FE12E59A109F78BF4A373541B3B9A1", 16), new BigInteger("1AB597A5B4477F59E39539007C7F977D1A567B92B043A49C6B61984C3FE3481AAF454CD41BA1F051626442B3C10", 16)); points[9] = curves[9].createPoint(new BigInteger("1A62BA79D98133A16BBAE7ED9A8E03C32E0824D57AEF72F88986874E5AAE49C27BED49A2A95058068426C2171E99FD3B43C5947C857D", 16), new BigInteger("70B5E1E14031C1F70BBEFE96BDDE66F451754B4CA5F48DA241F331AA396B8D1839A855C1769B1EA14BA53308B5E2723724E090E02DB9", 16)); - BigInteger[] n_s = new BigInteger[10]; - n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16); - n_s[1] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFB12EBCC7D7F29FF7701F", 16); - n_s[2] = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16); - n_s[3] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFB981960435FE5AB64236EF", 16); - n_s[4] = new BigInteger("40000000000000000000000069A779CAC1DABC6788F7474F", 16); - n_s[5] = new BigInteger("1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 16); - n_s[6] = new BigInteger("800000000000000000000000000000006759213AF182E987D3E17714907D470D", 16); - n_s[7] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC079C2F3825DA70D390FBBA588D4604022B7B7", 16); - n_s[8] = new BigInteger("40000000000000000000000000000000000000000000009C300B75A3FA824F22428FD28CE8812245EF44049B2D49", 16); - n_s[9] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16); - for (int i = 0; i < params.length; i++) { - params[i] = new ECDomainParameters(curves[i], points[i], n_s[i]); + params[i] = new ECDomainParameters(curves[i], points[i], n_s[i], h_s[i]); } for (int i = 0; i < oids.length; i++) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java index 06e2ef86d..d43a58ae0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ua/DSTU4145PointEncoder.java @@ -7,7 +7,6 @@ import org.spongycastle.math.ec.ECConstants; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECFieldElement; import org.spongycastle.math.ec.ECPoint; -import org.spongycastle.util.Arrays; /** * DSTU4145 encodes points somewhat differently than X9.62 @@ -15,21 +14,21 @@ import org.spongycastle.util.Arrays; */ public abstract class DSTU4145PointEncoder { - private static BigInteger trace(ECFieldElement fe) + private static ECFieldElement trace(ECFieldElement fe) { ECFieldElement t = fe; - for (int i = 0; i < fe.getFieldSize() - 1; i++) + for (int i = 1; i < fe.getFieldSize(); ++i) { t = t.square().add(fe); } - return t.toBigInteger(); + return t; } /** * Solves a quadratic equation*
+ *professionItems
is mandatory, all other parameters are * optional. * @@ -311,9 +311,8 @@ public class ProfessionInfo /** * Produce an object suitable for an ASN1OutputStream. - ** Returns: - *
** ProfessionInfo ::= SEQUENCE * { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java index 4f296ecf5..bd3f782b8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/isismtt/x509/Restriction.java @@ -6,7 +6,7 @@ import org.spongycastle.asn1.x500.DirectoryString; /** * Some other restriction regarding the usage of this certificate. - * + * **/ public ASN1Primitive toASN1Primitive() { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java index e63811030..35703140c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CertificationRequestInfo.java @@ -25,8 +25,8 @@ import org.spongycastle.asn1.x509.X509Name; * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} * * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { - * type ATTRIBUTE.&id({IOSet}), - * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type}) + * type ATTRIBUTE.&id({IOSet}), + * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type}) * } ** RestrictionSyntax ::= DirectoryString (SIZE(1..1024)) *@@ -64,12 +64,10 @@ public class Restriction /** * Produce an object suitable for an ASN1OutputStream. - * + ** Returns: - *
** RestrictionSyntax ::= DirectoryString (SIZE(1..1024)) - * ** * @return a DERObject diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java index 318da9a3d..016cef257 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/misc/MiscObjectIdentifiers.java @@ -36,7 +36,7 @@ public interface MiscObjectIdentifiers /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */ static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3"); - /** Verisign D&B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */ + /** Verisign D&B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */ static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15"); // diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java index 5dead09e3..d2ea42f8a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/CrlID.java @@ -9,7 +9,6 @@ import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERIA5String; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; @@ -39,7 +38,7 @@ public class CrlID crlNum = ASN1Integer.getInstance(o, true); break; case 2: - crlTime = DERGeneralizedTime.getInstance(o, true); + crlTime = ASN1GeneralizedTime.getInstance(o, true); break; default: throw new IllegalArgumentException( diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java index 522e1d7ea..69f716ba2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/ResponseData.java @@ -7,7 +7,6 @@ import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; import org.spongycastle.asn1.x509.Extensions; @@ -49,7 +48,7 @@ public class ResponseData */ public ResponseData( ResponderID responderID, - DERGeneralizedTime producedAt, + ASN1GeneralizedTime producedAt, ASN1Sequence responses, X509Extensions responseExtensions) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java index f3b29c99e..b11a9a246 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/ocsp/SingleResponse.java @@ -6,7 +6,6 @@ import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; import org.spongycastle.asn1.x509.Extensions; @@ -32,31 +31,13 @@ public class SingleResponse public SingleResponse( CertID certID, CertStatus certStatus, - DERGeneralizedTime thisUpdate, - DERGeneralizedTime nextUpdate, + ASN1GeneralizedTime thisUpdate, + ASN1GeneralizedTime nextUpdate, X509Extensions singleExtensions) { this(certID, certStatus, thisUpdate, nextUpdate, Extensions.getInstance(singleExtensions)); } - /** - * @deprecated use method taking ASN1GeneralizedTime and Extensions - * @param certID - * @param certStatus - * @param thisUpdate - * @param nextUpdate - * @param singleExtensions - */ - public SingleResponse( - CertID certID, - CertStatus certStatus, - DERGeneralizedTime thisUpdate, - DERGeneralizedTime nextUpdate, - Extensions singleExtensions) - { - this(certID, certStatus, ASN1GeneralizedTime.getInstance(thisUpdate), ASN1GeneralizedTime.getInstance(nextUpdate), Extensions.getInstance(singleExtensions)); - } - public SingleResponse( CertID certID, CertStatus certStatus, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java index 28ed26326..24dcde2c9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/oiw/ElGamalParameter.java @@ -23,7 +23,7 @@ public class ElGamalParameter this.g = new ASN1Integer(g); } - public ElGamalParameter( + private ElGamalParameter( ASN1Sequence seq) { Enumeration e = seq.getObjects(); @@ -32,6 +32,20 @@ public class ElGamalParameter g = (ASN1Integer)e.nextElement(); } + public static ElGamalParameter getInstance(Object o) + { + if (o instanceof ElGamalParameter) + { + return (ElGamalParameter)o; + } + else if (o != null) + { + return new ElGamalParameter(ASN1Sequence.getInstance(o)); + } + + return null; + } + public BigInteger getP() { return p.getPositiveValue(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java index 9a5268375..0110ee8bd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/pkcs/CRLBag.java @@ -56,19 +56,19 @@ public class CRLBag /** *- CRLBag ::= SEQUENCE { - crlId BAG-TYPE.&id ({CRLTypes}), - crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) - } - - x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1} - -- DER-encoded X.509 CRL stored in OCTET STRING - - CRLTypes BAG-TYPE ::= { - x509CRL, - ... -- For future extensions - } -+ * CRLBag ::= SEQUENCE { + * crlId BAG-TYPE.&id ({CRLTypes}), + * crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) + * } + * + * x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1} + * -- DER-encoded X.509 CRL stored in OCTET STRING + * + * CRLTypes BAG-TYPE ::= { + * x509CRL, + * ... -- For future extensions + * } + *z2 + z = beta
(X9.62 * D.1.6) The other solution isz + 1
. * - * @param beta The value to solve the qradratic equation for. + * @param beta The value to solve the quadratic equation for. * @return the solution forz2 + z = beta
or *null
if no solution exists. */ @@ -91,8 +90,8 @@ public abstract class DSTU4145PointEncoder if (!x.isZero()) { - ECFieldElement y = Q.getAffineYCoord().divide(x); - if (trace(y).equals(ECConstants.ONE)) + ECFieldElement z = Q.getAffineYCoord().divide(x); + if (trace(z).isOne()) { bytes[bytes.length - 1] |= 0x01; } @@ -118,39 +117,38 @@ public abstract class DSTU4145PointEncoder return curve.decodePoint(bp_enc);*/ - BigInteger k = BigInteger.valueOf(bytes[bytes.length - 1] & 0x1); - if (!trace(curve.fromBigInteger(new BigInteger(1, bytes))).equals(curve.getA().toBigInteger())) - { - bytes = Arrays.clone(bytes); - bytes[bytes.length - 1] ^= 0x01; - } + ECFieldElement k = curve.fromBigInteger(BigInteger.valueOf(bytes[bytes.length - 1] & 0x1)); + ECFieldElement xp = curve.fromBigInteger(new BigInteger(1, bytes)); + if (!trace(xp).equals(curve.getA())) + { + xp = xp.addOne(); + } + ECFieldElement yp = null; if (xp.isZero()) { - yp = (ECFieldElement.F2m)curve.getB(); - for (int i = 0; i < curve.getFieldSize() - 1; i++) - { - yp = yp.square(); - } + yp = curve.getB().sqrt(); } else { - ECFieldElement beta = xp.add(curve.getA()).add( - curve.getB().multiply(xp.square().invert())); + ECFieldElement beta = xp.square().invert().multiply(curve.getB()).add(curve.getA()).add(xp); ECFieldElement z = solveQuadraticEquation(curve, beta); - if (z == null) + if (z != null) { - throw new RuntimeException("Invalid point compression"); + if (!trace(z).equals(k)) + { + z = z.addOne(); + } + yp = xp.multiply(z); } - if (!trace(z).equals(k)) - { - z = z.addOne(); - } - yp = xp.multiply(z); } - return new ECPoint.F2m(curve, xp, yp); - } + if (yp == null) + { + throw new IllegalArgumentException("Invalid point compression"); + } + return curve.createPoint(xp.toBigInteger(), yp.toBigInteger()); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java index 7241b622d..6baad3c84 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/util/ASN1Dump.java @@ -3,7 +3,10 @@ package org.spongycastle.asn1.util; import java.io.IOException; import java.util.Enumeration; +import org.spongycastle.asn1.ASN1Boolean; import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Enumerated; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; @@ -11,8 +14,8 @@ import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.ASN1TaggedObject; +import org.spongycastle.asn1.ASN1UTCTime; import org.spongycastle.asn1.BERApplicationSpecific; -import org.spongycastle.asn1.BERConstructedOctetString; import org.spongycastle.asn1.BEROctetString; import org.spongycastle.asn1.BERSequence; import org.spongycastle.asn1.BERSet; @@ -21,16 +24,12 @@ import org.spongycastle.asn1.BERTags; import org.spongycastle.asn1.DERApplicationSpecific; import org.spongycastle.asn1.DERBMPString; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERBoolean; -import org.spongycastle.asn1.DEREnumerated; import org.spongycastle.asn1.DERExternal; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERIA5String; import org.spongycastle.asn1.DERNull; import org.spongycastle.asn1.DERPrintableString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERT61String; -import org.spongycastle.asn1.DERUTCTime; import org.spongycastle.asn1.DERUTF8String; import org.spongycastle.asn1.DERVisibleString; import org.spongycastle.util.encoders.Hex; @@ -172,7 +171,7 @@ public class ASN1Dump { ASN1OctetString oct = (ASN1OctetString)obj; - if (obj instanceof BEROctetString || obj instanceof BERConstructedOctetString) + if (obj instanceof BEROctetString) { buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] "); } @@ -193,9 +192,9 @@ public class ASN1Dump { buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl); } - else if (obj instanceof DERBoolean) + else if (obj instanceof ASN1Boolean) { - buf.append(indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl); + buf.append(indent + "Boolean(" + ((ASN1Boolean)obj).isTrue() + ")" + nl); } else if (obj instanceof ASN1Integer) { @@ -238,13 +237,13 @@ public class ASN1Dump { buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl); } - else if (obj instanceof DERUTCTime) + else if (obj instanceof ASN1UTCTime) { - buf.append(indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl); + buf.append(indent + "UTCTime(" + ((ASN1UTCTime)obj).getTime() + ") " + nl); } - else if (obj instanceof DERGeneralizedTime) + else if (obj instanceof ASN1GeneralizedTime) { - buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl); + buf.append(indent + "GeneralizedTime(" + ((ASN1GeneralizedTime)obj).getTime() + ") " + nl); } else if (obj instanceof BERApplicationSpecific) { @@ -254,9 +253,9 @@ public class ASN1Dump { buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl)); } - else if (obj instanceof DEREnumerated) + else if (obj instanceof ASN1Enumerated) { - DEREnumerated en = (DEREnumerated) obj; + ASN1Enumerated en = (ASN1Enumerated) obj; buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl); } else if (obj instanceof DERExternal) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java new file mode 100644 index 000000000..dfab0377d --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/AbstractX500NameStyle.java @@ -0,0 +1,192 @@ +package org.spongycastle.asn1.x500.style; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERUTF8String; +import org.spongycastle.asn1.x500.AttributeTypeAndValue; +import org.spongycastle.asn1.x500.RDN; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x500.X500NameStyle; + +/** + * This class provides some default behavior and common implementation for a + * X500NameStyle. It should be easily extendable to support implementing the + * desired X500NameStyle. + */ +public abstract class AbstractX500NameStyle + implements X500NameStyle +{ + + /** + * Tool function to shallow copy a Hashtable. + * + * @param paramsMap table to copy + * @return the copy of the table + */ + public static Hashtable copyHashTable(Hashtable paramsMap) + { + Hashtable newTable = new Hashtable(); + + Enumeration keys = paramsMap.keys(); + while (keys.hasMoreElements()) + { + Object key = keys.nextElement(); + newTable.put(key, paramsMap.get(key)); + } + + return newTable; + } + + private int calcHashCode(ASN1Encodable enc) + { + String value = IETFUtils.valueToString(enc); + value = IETFUtils.canonicalize(value); + return value.hashCode(); + } + + public int calculateHashCode(X500Name name) + { + int hashCodeValue = 0; + RDN[] rdns = name.getRDNs(); + + // this needs to be order independent, like equals + for (int i = 0; i != rdns.length; i++) + { + if (rdns[i].isMultiValued()) + { + AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues(); + + for (int j = 0; j != atv.length; j++) + { + hashCodeValue ^= atv[j].getType().hashCode(); + hashCodeValue ^= calcHashCode(atv[j].getValue()); + } + } + else + { + hashCodeValue ^= rdns[i].getFirst().getType().hashCode(); + hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue()); + } + } + + return hashCodeValue; + } + + + /** + * For all string values starting with '#' is assumed, that these are + * already valid ASN.1 objects encoded in hex. + *+ * All other string values are send to + * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)}. + *
+ * Subclasses should overwrite + * {@link AbstractX500NameStyle#encodeStringValue(ASN1ObjectIdentifier, String)} + * to change the encoding of specific types. + * + * @param oid the DN name of the value. + * @param value the String representation of the value. + */ + public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value) + { + if (value.length() != 0 && value.charAt(0) == '#') + { + try + { + return IETFUtils.valueFromHexString(value, 1); + } + catch (IOException e) + { + throw new RuntimeException("can't recode value for oid " + oid.getId()); + } + } + + if (value.length() != 0 && value.charAt(0) == '\\') + { + value = value.substring(1); + } + + return encodeStringValue(oid, value); + } + + /** + * Encoded every value into a UTF8String. + *+ * Subclasses should overwrite + * this method to change the encoding of specific types. + *
+ * + * @param oid the DN oid of the value + * @param value the String representation of the value + * @return a the value encoded into a ASN.1 object. Never returnsnull
. + */ + protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, String value) + { + return new DERUTF8String(value); + } + + public boolean areEqual(X500Name name1, X500Name name2) + { + RDN[] rdns1 = name1.getRDNs(); + RDN[] rdns2 = name2.getRDNs(); + + if (rdns1.length != rdns2.length) + { + return false; + } + + boolean reverse = false; + + if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null) + { + reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward + } + + for (int i = 0; i != rdns1.length; i++) + { + if (!foundMatch(reverse, rdns1[i], rdns2)) + { + return false; + } + } + + return true; + } + + private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs) + { + if (reverse) + { + for (int i = possRDNs.length - 1; i >= 0; i--) + { + if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) + { + possRDNs[i] = null; + return true; + } + } + } + else + { + for (int i = 0; i != possRDNs.length; i++) + { + if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) + { + possRDNs[i] = null; + return true; + } + } + } + + return false; + } + + protected boolean rdnAreEqual(RDN rdn1, RDN rdn2) + { + return IETFUtils.rDNAreEqual(rdn1, rdn2); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java index b4d01f44f..cb92a0bd1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/BCStyle.java @@ -1,7 +1,5 @@ package org.spongycastle.asn1.x500.style; -import java.io.IOException; -import java.util.Enumeration; import java.util.Hashtable; import org.spongycastle.asn1.ASN1Encodable; @@ -9,16 +7,14 @@ import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERIA5String; import org.spongycastle.asn1.DERPrintableString; -import org.spongycastle.asn1.DERUTF8String; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.x500.AttributeTypeAndValue; import org.spongycastle.asn1.x500.RDN; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x500.X500NameStyle; import org.spongycastle.asn1.x509.X509ObjectIdentifiers; public class BCStyle - implements X500NameStyle + extends AbstractX500NameStyle { /** * country code - StringType(SIZE(2)) @@ -285,42 +281,24 @@ public class BCStyle defaultSymbols = copyHashTable(DefaultSymbols); defaultLookUp = copyHashTable(DefaultLookUp); } - - public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value) - { - if (value.length() != 0 && value.charAt(0) == '#') - { - try - { - return IETFUtils.valueFromHexString(value, 1); - } - catch (IOException e) - { - throw new RuntimeException("can't recode value for oid " + oid.getId()); - } - } - else - { - if (value.length() != 0 && value.charAt(0) == '\\') - { - value = value.substring(1); - } - if (oid.equals(EmailAddress) || oid.equals(DC)) - { - return new DERIA5String(value); - } - else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility) - { - return new ASN1GeneralizedTime(value); - } - else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER) - || oid.equals(TELEPHONE_NUMBER)) - { - return new DERPrintableString(value); - } - } - return new DERUTF8String(value); + protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, + String value) { + if (oid.equals(EmailAddress) || oid.equals(DC)) + { + return new DERIA5String(value); + } + else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility) + { + return new ASN1GeneralizedTime(value); + } + else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER) + || oid.equals(TELEPHONE_NUMBER)) + { + return new DERPrintableString(value); + } + + return super.encodeStringValue(oid, value); } public String oidToDisplayName(ASN1ObjectIdentifier oid) @@ -338,109 +316,11 @@ public class BCStyle return IETFUtils.decodeAttrName(attrName, defaultLookUp); } - public boolean areEqual(X500Name name1, X500Name name2) - { - RDN[] rdns1 = name1.getRDNs(); - RDN[] rdns2 = name2.getRDNs(); - - if (rdns1.length != rdns2.length) - { - return false; - } - - boolean reverse = false; - - if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null) - { - reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward - } - - for (int i = 0; i != rdns1.length; i++) - { - if (!foundMatch(reverse, rdns1[i], rdns2)) - { - return false; - } - } - - return true; - } - - private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs) - { - if (reverse) - { - for (int i = possRDNs.length - 1; i >= 0; i--) - { - if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) - { - possRDNs[i] = null; - return true; - } - } - } - else - { - for (int i = 0; i != possRDNs.length; i++) - { - if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) - { - possRDNs[i] = null; - return true; - } - } - } - - return false; - } - - protected boolean rdnAreEqual(RDN rdn1, RDN rdn2) - { - return IETFUtils.rDNAreEqual(rdn1, rdn2); - } - public RDN[] fromString(String dirName) { return IETFUtils.rDNsFromString(dirName, this); } - public int calculateHashCode(X500Name name) - { - int hashCodeValue = 0; - RDN[] rdns = name.getRDNs(); - - // this needs to be order independent, like equals - for (int i = 0; i != rdns.length; i++) - { - if (rdns[i].isMultiValued()) - { - AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues(); - - for (int j = 0; j != atv.length; j++) - { - hashCodeValue ^= atv[j].getType().hashCode(); - hashCodeValue ^= calcHashCode(atv[j].getValue()); - } - } - else - { - hashCodeValue ^= rdns[i].getFirst().getType().hashCode(); - hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue()); - } - } - - return hashCodeValue; - } - - private int calcHashCode(ASN1Encodable enc) - { - String value = IETFUtils.valueToString(enc); - - value = IETFUtils.canonicalize(value); - - return value.hashCode(); - } - public String toString(X500Name name) { StringBuffer buf = new StringBuffer(); @@ -465,17 +345,5 @@ public class BCStyle return buf.toString(); } - private static Hashtable copyHashTable(Hashtable paramsMap) - { - Hashtable newTable = new Hashtable(); - Enumeration keys = paramsMap.keys(); - while (keys.hasMoreElements()) - { - Object key = keys.nextElement(); - newTable.put(key, paramsMap.get(key)); - } - - return newTable; - } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java index ce2cbea08..83825e6c2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/RFC4519Style.java @@ -1,21 +1,17 @@ package org.spongycastle.asn1.x500.style; -import java.io.IOException; -import java.util.Enumeration; import java.util.Hashtable; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERIA5String; import org.spongycastle.asn1.DERPrintableString; -import org.spongycastle.asn1.DERUTF8String; -import org.spongycastle.asn1.x500.AttributeTypeAndValue; import org.spongycastle.asn1.x500.RDN; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x500.X500NameStyle; public class RFC4519Style - implements X500NameStyle + extends AbstractX500NameStyle { public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15"); public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6"); @@ -179,37 +175,19 @@ public class RFC4519Style defaultLookUp = copyHashTable(DefaultLookUp); } - public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value) - { - if (value.length() != 0 && value.charAt(0) == '#') + protected ASN1Encodable encodeStringValue(ASN1ObjectIdentifier oid, + String value) { + if (oid.equals(dc)) { - try - { - return IETFUtils.valueFromHexString(value, 1); - } - catch (IOException e) - { - throw new RuntimeException("can't recode value for oid " + oid.getId()); - } + return new DERIA5String(value); } - else + else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier) + || oid.equals(telephoneNumber)) { - if (value.length() != 0 && value.charAt(0) == '\\') - { - value = value.substring(1); - } - if (oid.equals(dc)) - { - return new DERIA5String(value); - } - else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier) - || oid.equals(telephoneNumber)) - { - return new DERPrintableString(value); - } + return new DERPrintableString(value); } - return new DERUTF8String(value); + return super.encodeStringValue(oid, value); } public String oidToDisplayName(ASN1ObjectIdentifier oid) @@ -227,67 +205,6 @@ public class RFC4519Style return IETFUtils.decodeAttrName(attrName, defaultLookUp); } - public boolean areEqual(X500Name name1, X500Name name2) - { - RDN[] rdns1 = name1.getRDNs(); - RDN[] rdns2 = name2.getRDNs(); - - if (rdns1.length != rdns2.length) - { - return false; - } - - boolean reverse = false; - - if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null) - { - reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward - } - - for (int i = 0; i != rdns1.length; i++) - { - if (!foundMatch(reverse, rdns1[i], rdns2)) - { - return false; - } - } - - return true; - } - - private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs) - { - if (reverse) - { - for (int i = possRDNs.length - 1; i >= 0; i--) - { - if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) - { - possRDNs[i] = null; - return true; - } - } - } - else - { - for (int i = 0; i != possRDNs.length; i++) - { - if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i])) - { - possRDNs[i] = null; - return true; - } - } - } - - return false; - } - - protected boolean rdnAreEqual(RDN rdn1, RDN rdn2) - { - return IETFUtils.rDNAreEqual(rdn1, rdn2); - } - // parse backwards public RDN[] fromString(String dirName) { @@ -302,43 +219,6 @@ public class RFC4519Style return res; } - public int calculateHashCode(X500Name name) - { - int hashCodeValue = 0; - RDN[] rdns = name.getRDNs(); - - // this needs to be order independent, like equals - for (int i = 0; i != rdns.length; i++) - { - if (rdns[i].isMultiValued()) - { - AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues(); - - for (int j = 0; j != atv.length; j++) - { - hashCodeValue ^= atv[j].getType().hashCode(); - hashCodeValue ^= calcHashCode(atv[j].getValue()); - } - } - else - { - hashCodeValue ^= rdns[i].getFirst().getType().hashCode(); - hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue()); - } - } - - return hashCodeValue; - } - - private int calcHashCode(ASN1Encodable enc) - { - String value = IETFUtils.valueToString(enc); - - value = IETFUtils.canonicalize(value); - - return value.hashCode(); - } - // convert in reverse public String toString(X500Name name) { @@ -364,17 +244,5 @@ public class RFC4519Style return buf.toString(); } - private static Hashtable copyHashTable(Hashtable paramsMap) - { - Hashtable newTable = new Hashtable(); - - Enumeration keys = paramsMap.keys(); - while (keys.hasMoreElements()) - { - Object key = keys.nextElement(); - newTable.put(key, paramsMap.get(key)); - } - - return newTable; - } + } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java index d880c63f5..65ce98654 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x500/style/X500NameTokenizer.java @@ -6,7 +6,7 @@ package org.spongycastle.asn1.x500.style; * lightweight Java environment don't support classes like * StringTokenizer. */ -class X500NameTokenizer +public class X500NameTokenizer { private String value; private int index; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java index 0c07c49b9..f57972500 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AlgorithmIdentifier.java @@ -8,7 +8,6 @@ import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; public class AlgorithmIdentifier @@ -64,30 +63,6 @@ public class AlgorithmIdentifier this.objectId = new ASN1ObjectIdentifier(objectId); } - /** - * @deprecated use ASN1ObjectIdentifier - * @param objectId - */ - public AlgorithmIdentifier( - DERObjectIdentifier objectId) - { - this.objectId = new ASN1ObjectIdentifier(objectId.getId()); - } - - /** - * @deprecated use ASN1ObjectIdentifier - * @param objectId - * @param parameters - */ - public AlgorithmIdentifier( - DERObjectIdentifier objectId, - ASN1Encodable parameters) - { - parametersDefined = true; - this.objectId = new ASN1ObjectIdentifier(objectId.getId()); - this.parameters = parameters; - } - public AlgorithmIdentifier( ASN1ObjectIdentifier objectId, ASN1Encodable parameters) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java index a6c8ae7ab..2324f7471 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityInformationAccess.java @@ -60,6 +60,12 @@ public class AuthorityInformationAccess } } + public AuthorityInformationAccess( + AccessDescription description) + { + this.descriptions = new AccessDescription[]{ description }; + } + /** * create an AuthorityInformationAccess with the oid and location provided. */ @@ -67,12 +73,9 @@ public class AuthorityInformationAccess ASN1ObjectIdentifier oid, GeneralName location) { - descriptions = new AccessDescription[1]; - - descriptions[0] = new AccessDescription(oid, location); + this(new AccessDescription(oid, location)); } - /** * * @return the access descriptions contained in this object. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java index 10401fcb8..5178e3b8e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/AuthorityKeyIdentifier.java @@ -101,7 +101,7 @@ public class AuthorityKeyIdentifier * publicKey.getEncoded()).readObject()); * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki); ** Returns: - *
** CertificatePair ::= SEQUENCE { * forward [0] Certificate OPTIONAL, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java index f47041469..12834c854 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/PrivateKeyUsagePeriod.java @@ -3,11 +3,11 @@ package org.spongycastle.asn1.x509; import java.util.Enumeration; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; @@ -36,7 +36,7 @@ public class PrivateKeyUsagePeriod return null; } - private DERGeneralizedTime _notBefore, _notAfter; + private ASN1GeneralizedTime _notBefore, _notAfter; private PrivateKeyUsagePeriod(ASN1Sequence seq) { @@ -47,21 +47,21 @@ public class PrivateKeyUsagePeriod if (tObj.getTagNo() == 0) { - _notBefore = DERGeneralizedTime.getInstance(tObj, false); + _notBefore = ASN1GeneralizedTime.getInstance(tObj, false); } else if (tObj.getTagNo() == 1) { - _notAfter = DERGeneralizedTime.getInstance(tObj, false); + _notAfter = ASN1GeneralizedTime.getInstance(tObj, false); } } } - public DERGeneralizedTime getNotBefore() + public ASN1GeneralizedTime getNotBefore() { return _notBefore; } - public DERGeneralizedTime getNotAfter() + public ASN1GeneralizedTime getNotAfter() { return _notAfter; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java index 96ff98e3e..2a0272b81 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/SubjectKeyIdentifier.java @@ -5,8 +5,6 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.digests.SHA1Digest; /** * The SubjectKeyIdentifier object. @@ -67,69 +65,4 @@ public class SubjectKeyIdentifier { return new DEROctetString(keyidentifier); } - - - /** - * Calculates the keyidentifier using a SHA1 hash over the BIT STRING - * from SubjectPublicKeyInfo as defined in RFC3280. - * - * @param spki the subject public key info. - * @deprecated - */ - public SubjectKeyIdentifier( - SubjectPublicKeyInfo spki) - { - this.keyidentifier = getDigest(spki); - } - - /** - * Return a RFC 3280 type 1 key identifier. As in: - **/ public abstract class X509NameEntryConverter { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java index f5fbc4aa7..72433a0ed 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/NameOrPseudonym.java @@ -60,9 +60,8 @@ public class NameOrPseudonym /** * Constructor from DirectoryString. - * + *- * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the - * value of the BIT STRING subjectPublicKey (excluding the tag, - * length, and number of unused bits). - *- * @param keyInfo the key info object containing the subjectPublicKey field. - * @return the key identifier. - * @deprecated use org.spongycastle.cert.X509ExtensionUtils.createSubjectKeyIdentifier - */ - public static SubjectKeyIdentifier createSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo) - { - return new SubjectKeyIdentifier(keyInfo); - } - - /** - * Return a RFC 3280 type 2 key identifier. As in: - *- * (2) The keyIdentifier is composed of a four bit type field with - * the value 0100 followed by the least significant 60 bits of the - * SHA-1 hash of the value of the BIT STRING subjectPublicKey. - *- * @param keyInfo the key info object containing the subjectPublicKey field. - * @return the key identifier. - * @deprecated use org.spongycastle.cert.X509ExtensionUtils.createTruncatedSubjectKeyIdentifier - */ - public static SubjectKeyIdentifier createTruncatedSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo) - { - byte[] dig = getDigest(keyInfo); - byte[] id = new byte[8]; - - System.arraycopy(dig, dig.length - 8, id, 0, id.length); - - id[0] &= 0x0f; - id[0] |= 0x40; - - return new SubjectKeyIdentifier(id); - } - - private static byte[] getDigest(SubjectPublicKeyInfo spki) - { - Digest digest = new SHA1Digest(); - byte[] resBuf = new byte[digest.getDigestSize()]; - - byte[] bytes = spki.getPublicKeyData().getBytes(); - digest.update(bytes, 0, bytes.length); - digest.doFinal(resBuf, 0); - return resBuf; - } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java index e21c0bd94..76b464830 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/TBSCertList.java @@ -3,15 +3,15 @@ package org.spongycastle.asn1.x509; import java.util.Enumeration; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.ASN1UTCTime; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; -import org.spongycastle.asn1.DERUTCTime; import org.spongycastle.asn1.x500.X500Name; /** @@ -190,8 +190,8 @@ public class TBSCertList thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); if (seqPos < seq.size() - && (seq.getObjectAt(seqPos) instanceof DERUTCTime - || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime + && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime + || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime || seq.getObjectAt(seqPos) instanceof Time)) { nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/Time.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/Time.java index e42d837cc..0cda6abf0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/Time.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/Time.java @@ -3,12 +3,15 @@ package org.spongycastle.asn1.x509; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.SimpleTimeZone; import org.spongycastle.asn1.ASN1Choice; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1TaggedObject; +import org.spongycastle.asn1.ASN1UTCTime; import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERUTCTime; @@ -28,8 +31,8 @@ public class Time public Time( ASN1Primitive time) { - if (!(time instanceof DERUTCTime) - && !(time instanceof DERGeneralizedTime)) + if (!(time instanceof ASN1UTCTime) + && !(time instanceof ASN1GeneralizedTime)) { throw new IllegalArgumentException("unknown object passed to Time"); } @@ -38,28 +41,61 @@ public class Time } /** - * creates a time object from a given date - if the date is between 1950 + * Creates a time object from a given date - if the date is between 1950 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime * is used. + * + * @param time a date object representing the time of interest. */ public Time( - Date date) + Date time) { SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss"); dateF.setTimeZone(tz); - String d = dateF.format(date) + "Z"; + String d = dateF.format(time) + "Z"; int year = Integer.parseInt(d.substring(0, 4)); if (year < 1950 || year > 2049) { - time = new DERGeneralizedTime(d); + this.time = new DERGeneralizedTime(d); } else { - time = new DERUTCTime(d.substring(2)); + this.time = new DERUTCTime(d.substring(2)); + } + } + + /** + * Creates a time object from a given date and locale - if the date is between 1950 + * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime + * is used. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. + * + * @param time a date object representing the time of interest. + * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value. + */ + public Time( + Date time, + Locale locale) + { + SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); + SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale); + + dateF.setTimeZone(tz); + + String d = dateF.format(time) + "Z"; + int year = Integer.parseInt(d.substring(0, 4)); + + if (year < 1950 || year > 2049) + { + this.time = new DERGeneralizedTime(d); + } + else + { + this.time = new DERUTCTime(d.substring(2)); } } @@ -70,13 +106,13 @@ public class Time { return (Time)obj; } - else if (obj instanceof DERUTCTime) + else if (obj instanceof ASN1UTCTime) { - return new Time((DERUTCTime)obj); + return new Time((ASN1UTCTime)obj); } - else if (obj instanceof DERGeneralizedTime) + else if (obj instanceof ASN1GeneralizedTime) { - return new Time((DERGeneralizedTime)obj); + return new Time((ASN1GeneralizedTime)obj); } throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName()); @@ -84,13 +120,13 @@ public class Time public String getTime() { - if (time instanceof DERUTCTime) + if (time instanceof ASN1UTCTime) { - return ((DERUTCTime)time).getAdjustedTime(); + return ((ASN1UTCTime)time).getAdjustedTime(); } else { - return ((DERGeneralizedTime)time).getTime(); + return ((ASN1GeneralizedTime)time).getTime(); } } @@ -98,13 +134,13 @@ public class Time { try { - if (time instanceof DERUTCTime) + if (time instanceof ASN1UTCTime) { - return ((DERUTCTime)time).getAdjustedDate(); + return ((ASN1UTCTime)time).getAdjustedDate(); } else { - return ((DERGeneralizedTime)time).getDate(); + return ((ASN1GeneralizedTime)time).getDate(); } } catch (ParseException e) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java index b6a3ee73d..26328cc51 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/V3TBSCertificateGenerator.java @@ -2,10 +2,10 @@ package org.spongycastle.asn1.x509; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1UTCTime; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; -import org.spongycastle.asn1.DERUTCTime; import org.spongycastle.asn1.x500.X500Name; /** @@ -74,7 +74,7 @@ public class V3TBSCertificateGenerator } public void setStartDate( - DERUTCTime startDate) + ASN1UTCTime startDate) { this.startDate = new Time(startDate); } @@ -86,7 +86,7 @@ public class V3TBSCertificateGenerator } public void setEndDate( - DERUTCTime endDate) + ASN1UTCTime endDate) { this.endDate = new Time(endDate); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java index 8a7defa95..6537d80f0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extension.java @@ -2,11 +2,11 @@ package org.spongycastle.asn1.x509; import java.io.IOException; +import org.spongycastle.asn1.ASN1Boolean; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.DERBoolean; /** * an object for the elements in the X.509 V3 extension block. @@ -173,7 +173,7 @@ public class X509Extension ASN1OctetString value; public X509Extension( - DERBoolean critical, + ASN1Boolean critical, ASN1OctetString value) { this.critical = critical.isTrue(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java index edf116014..fb2cf9235 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509Extensions.java @@ -4,6 +4,7 @@ import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; +import org.spongycastle.asn1.ASN1Boolean; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1ObjectIdentifier; @@ -11,8 +12,6 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERBoolean; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; /** @@ -259,7 +258,7 @@ public class X509Extensions if (s.size() == 3) { - extensions.put(s.getObjectAt(0), new X509Extension(DERBoolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2)))); + extensions.put(s.getObjectAt(0), new X509Extension(ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2)))); } else if (s.size() == 2) { @@ -368,17 +367,6 @@ public class X509Extensions * * @return the extension if it's present, null otherwise. */ - public X509Extension getExtension( - DERObjectIdentifier oid) - { - return (X509Extension)extensions.get(oid); - } - - /** - * @deprecated - * @param oid - * @return - */ public X509Extension getExtension( ASN1ObjectIdentifier oid) { @@ -410,7 +398,7 @@ public class X509Extensions if (ext.isCritical()) { - v.add(DERBoolean.TRUE); + v.add(ASN1Boolean.TRUE); } v.add(ext.getValue()); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java index 16c075274..af8fc9bb4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509ExtensionsGenerator.java @@ -7,7 +7,6 @@ import java.util.Vector; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DEROctetString; /** @@ -28,28 +27,6 @@ public class X509ExtensionsGenerator extOrdering = new Vector(); } - /** - * @deprecated use ASN1ObjectIdentifier - */ - public void addExtension( - DERObjectIdentifier oid, - boolean critical, - ASN1Encodable value) - { - addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); - } - - /** - * @deprecated use ASN1ObjectIdentifier - */ - public void addExtension( - DERObjectIdentifier oid, - boolean critical, - byte[] value) - { - addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value); - } - /** * Add an extension with the given oid and the passed in value to be included * in the OCTET STRING associated with the extension. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java index f831582d2..bcbcc28e3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/X509NameEntryConverter.java @@ -23,7 +23,7 @@ import org.spongycastle.util.Strings; * ASN1ObjectIdentifier oid, * String value) * { - * if (str.length() != 0 && str.charAt(0) == '#') + * if (str.length() != 0 && str.charAt(0) == '#') * { * return convertHexEncoded(str, 1); * } @@ -45,6 +45,7 @@ import org.spongycastle.util.Strings; * } * } * } + ** The sequence is of type NameOrPseudonym: - *
** NameOrPseudonym ::= CHOICE { * surAndGivenName SEQUENCE { @@ -159,9 +158,8 @@ public class NameOrPseudonym /** * Produce an object suitable for an ASN1OutputStream. - * + ** Returns: - *
** NameOrPseudonym ::= CHOICE { * surAndGivenName SEQUENCE { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java index ca34b4f57..dec8ded64 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x509/sigi/PersonalData.java @@ -18,7 +18,7 @@ import org.spongycastle.asn1.x500.DirectoryString; /** * Contains personal data for the otherName field in the subjectAltNames * extension. - * + * ** PersonalData ::= SEQUENCE { * nameOrPseudonym NameOrPseudonym, @@ -169,9 +169,8 @@ public class PersonalData /** * Produce an object suitable for an ASN1OutputStream. - * + ** Returns: - *
** PersonalData ::= SEQUENCE { * nameOrPseudonym NameOrPseudonym, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java index 2d63bf4c7..38575d893 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHDomainParameters.java @@ -1,5 +1,6 @@ package org.spongycastle.asn1.x9; +import java.math.BigInteger; import java.util.Enumeration; import org.spongycastle.asn1.ASN1Encodable; @@ -38,6 +39,29 @@ public class DHDomainParameters + obj.getClass().getName()); } + public DHDomainParameters(BigInteger p, BigInteger g, BigInteger q, BigInteger j, + DHValidationParms validationParms) + { + if (p == null) + { + throw new IllegalArgumentException("'p' cannot be null"); + } + if (g == null) + { + throw new IllegalArgumentException("'g' cannot be null"); + } + if (q == null) + { + throw new IllegalArgumentException("'q' cannot be null"); + } + + this.p = new ASN1Integer(p); + this.g = new ASN1Integer(g); + this.q = new ASN1Integer(q); + this.j = new ASN1Integer(j); + this.validationParms = validationParms; + } + public DHDomainParameters(ASN1Integer p, ASN1Integer g, ASN1Integer q, ASN1Integer j, DHValidationParms validationParms) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java index 8f5ece200..f70991c08 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/DHValidationParms.java @@ -21,17 +21,16 @@ public class DHValidationParms extends ASN1Object public static DHValidationParms getInstance(Object obj) { - if (obj == null || obj instanceof DHDomainParameters) + if (obj instanceof DHValidationParms) { return (DHValidationParms)obj; } - - if (obj instanceof ASN1Sequence) + else if (obj != null) { - return new DHValidationParms((ASN1Sequence)obj); + return new DHValidationParms(ASN1Sequence.getInstance(obj)); } - throw new IllegalArgumentException("Invalid DHValidationParms: " + obj.getClass().getName()); + return null; } public DHValidationParms(DERBitString seed, ASN1Integer pgenCounter) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java index e60629d9d..c5b471aef 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/ECNamedCurveTable.java @@ -43,6 +43,35 @@ public class ECNamedCurveTable return ecP; } + /** + * return the object identifier signified by the passed in name. Null + * if there is no object identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static ASN1ObjectIdentifier getOID( + String name) + { + ASN1ObjectIdentifier oid = X962NamedCurves.getOID(name); + + if (oid == null) + { + oid = SECNamedCurves.getOID(name); + } + + if (oid == null) + { + oid = TeleTrusTNamedCurves.getOID(name); + } + + if (oid == null) + { + oid = NISTNamedCurves.getOID(name); + } + + return oid; + } + /** * return a X9ECParameters object representing the passed in named * curve. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java index aea4c032a..61a6fc4b5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962NamedCurves.java @@ -19,17 +19,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp192v1 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), - new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); + new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), + n, h); return new X9ECParameters( cFp192v1, cFp192v1.decodePoint( Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), - new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5")); } }; @@ -38,17 +41,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp192v2 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), - new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16)); + new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16), + n, h); return new X9ECParameters( cFp192v2, cFp192v2.decodePoint( Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")), - new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6")); } }; @@ -57,17 +63,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp192v3 = new ECCurve.Fp( new BigInteger("6277101735386680763835789423207666416083908700390324961279"), new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), - new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16)); + new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16), + n, h); return new X9ECParameters( cFp192v3, cFp192v3.decodePoint( Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")), - new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e")); } }; @@ -76,17 +85,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp239v1 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), - new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), + n, h); return new X9ECParameters( cFp239v1, cFp239v1.decodePoint( Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), - new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d")); } }; @@ -95,17 +107,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp239v2 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), - new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16)); + new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16), + n, h); return new X9ECParameters( cFp239v2, cFp239v2.decodePoint( Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")), - new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616")); } }; @@ -114,17 +129,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp239v3 = new ECCurve.Fp( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), - new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16)); + new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16), + n, h); return new X9ECParameters( cFp239v3, cFp239v3.decodePoint( Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")), - new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff")); } }; @@ -133,17 +151,20 @@ public class X962NamedCurves { protected X9ECParameters createParameters() { + BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16); + BigInteger h = BigInteger.valueOf(1); + ECCurve cFp256v1 = new ECCurve.Fp( new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"), new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16), - new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)); + new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16), + n, h); return new X9ECParameters( cFp256v1, cFp256v1.decodePoint( Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")), - new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16), - BigInteger.valueOf(1), + n, h, Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90")); } }; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java index 49e73a160..7c95793fe 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X962Parameters.java @@ -74,7 +74,7 @@ public class X962Parameters ** Parameters ::= CHOICE { * ecParameters ECParameters, - * namedCurve CURVES.&id({CurveNames}), + * namedCurve CURVES.&id({CurveNames}), * implicitlyCA NULL * } *diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java index f9673c2f3..f2d2976c9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9Curve.java @@ -11,6 +11,7 @@ import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERSequence; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; /** @@ -46,6 +47,8 @@ public class X9Curve X9FieldID fieldID, ASN1Sequence seq) { + // TODO Is it possible to get the order(n) and cofactor(h) too? + fieldIdentifier = fieldID.getIdentifier(); if (fieldIdentifier.equals(prime_field)) { @@ -86,7 +89,6 @@ public class X9Curve } X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0)); X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1)); - // TODO Is it possible to get the order (n) and cofactor(h) too? curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger()); } else @@ -102,11 +104,11 @@ public class X9Curve private void setFieldIdentifier() { - if (curve instanceof ECCurve.Fp) + if (ECAlgorithms.isFpCurve(curve)) { fieldIdentifier = prime_field; } - else if (curve instanceof ECCurve.F2m) + else if (ECAlgorithms.isF2mCurve(curve)) { fieldIdentifier = characteristic_two_field; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java index 80eb35fe2..e0a926f29 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9ECParameters.java @@ -9,8 +9,10 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERSequence; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.field.PolynomialExtensionField; /** * ASN.1 def for Elliptic-Curve ECParameters structure. See @@ -108,18 +110,30 @@ public class X9ECParameters this.h = h; this.seed = seed; - if (curve instanceof ECCurve.Fp) + if (ECAlgorithms.isFpCurve(curve)) { - this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ()); + this.fieldID = new X9FieldID(curve.getField().getCharacteristic()); + } + else if (ECAlgorithms.isF2mCurve(curve)) + { + PolynomialExtensionField field = (PolynomialExtensionField)curve.getField(); + int[] exponents = field.getMinimalPolynomial().getExponentsPresent(); + if (exponents.length == 3) + { + this.fieldID = new X9FieldID(exponents[2], exponents[1]); + } + else if (exponents.length == 5) + { + this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]); + } + else + { + throw new IllegalArgumentException("Only trinomial and pentomial curves are supported"); + } } else { - if (curve instanceof ECCurve.F2m) - { - ECCurve.F2m curveF2m = (ECCurve.F2m)curve; - this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(), - curveF2m.getK2(), curveF2m.getK3()); - } + throw new IllegalArgumentException("'curve' is of an unsupported type"); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java index e73fad726..831fc0b33 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/asn1/x9/X9FieldID.java @@ -32,6 +32,20 @@ public class X9FieldID this.parameters = new ASN1Integer(primeP); } + /** + * Constructor for elliptic curves over binary fields + *F2m
. + * @param m The exponentm
of + *F2m
. + * @param k1 The integerk1
wherexm + + * xk1 + 1
+ * represents the reduction polynomialf(z)
. + */ + public X9FieldID(int m, int k1) + { + this(m, k1, 0, 0); + } + /** * Constructor for elliptic curves over binary fields *F2m
. @@ -55,11 +69,21 @@ public class X9FieldID if (k2 == 0) { + if (k3 != 0) + { + throw new IllegalArgumentException("inconsistent k values"); + } + fieldIdParams.add(tpBasis); fieldIdParams.add(new ASN1Integer(k1)); } else { + if (k2 <= k1 || k3 <= k2) + { + throw new IllegalArgumentException("inconsistent k values"); + } + fieldIdParams.add(ppBasis); ASN1EncodableVector pentanomialParams = new ASN1EncodableVector(); pentanomialParams.add(new ASN1Integer(k1)); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java index 941943322..28e5a5b9b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/BufferedBlockCipher.java @@ -48,13 +48,13 @@ public class BufferedBlockCipher pgpCFB = (idx > 0 && name.startsWith("PGP", idx)); - if (pgpCFB) + if (pgpCFB || cipher instanceof StreamCipher) { partialBlockOkay = true; } else { - partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("GCFB", idx) ||name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx))); + partialBlockOkay = (idx > 0 && (name.startsWith("OpenPGP", idx))); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java new file mode 100644 index 000000000..653182cd8 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingCipher.java @@ -0,0 +1,31 @@ +package org.spongycastle.crypto; + +/** + * Ciphers producing a key stream which can be reset to particular points in the stream implement this. + */ +public interface SkippingCipher +{ + /** + * Skip numberOfBytes forwards, or backwards. + * + * @param numberOfBytes the number of bytes to skip (positive forward, negative backwards). + * @return the number of bytes actually skipped. + * @throws java.lang.IllegalArgumentException if numberOfBytes is an invalid value. + */ + long skip(long numberOfBytes); + + /** + * Reset the cipher and then skip forward to a given position. + * + * @param position the number of bytes in to set the cipher state to. + * @return the byte position moved to. + */ + long seekTo(long position); + + /** + * Return the current "position" of the cipher + * + * @return the current byte position. + */ + long getPosition(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java new file mode 100644 index 000000000..1e704bada --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/SkippingStreamCipher.java @@ -0,0 +1,9 @@ +package org.spongycastle.crypto; + +/** + * General interface for a stream cipher that supports skipping. + */ +public interface SkippingStreamCipher + extends StreamCipher, SkippingCipher +{ +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java index d1fa86e0a..58410183e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamBlockCipher.java @@ -1,108 +1,58 @@ package org.spongycastle.crypto; /** - * a wrapper for block ciphers with a single byte block size, so that they - * can be treated like stream ciphers. + * A parent class for block cipher modes that do not require block aligned data to be processed, but can function in + * a streaming mode. */ -public class StreamBlockCipher - implements StreamCipher +public abstract class StreamBlockCipher + implements BlockCipher, StreamCipher { - private BlockCipher cipher; + private final BlockCipher cipher; - private byte[] oneByte = new byte[1]; - - /** - * basic constructor. - * - * @param cipher the block cipher to be wrapped. - * @exception IllegalArgumentException if the cipher has a block size other than - * one. - */ - public StreamBlockCipher( - BlockCipher cipher) + protected StreamBlockCipher(BlockCipher cipher) { - if (cipher.getBlockSize() != 1) - { - throw new IllegalArgumentException("block cipher block size != 1."); - } - this.cipher = cipher; } /** - * initialise the underlying cipher. + * return the underlying block cipher that we are wrapping. * - * @param forEncryption true if we are setting up for encryption, false otherwise. - * @param params the necessary parameters for the underlying cipher to be initialised. + * @return the underlying block cipher that we are wrapping. */ - public void init( - boolean forEncryption, - CipherParameters params) + public BlockCipher getUnderlyingCipher() { - cipher.init(forEncryption, params); + return cipher; } - /** - * return the name of the algorithm we are wrapping. - * - * @return the name of the algorithm we are wrapping. - */ - public String getAlgorithmName() + public final byte returnByte(byte in) { - return cipher.getAlgorithmName(); + return calculateByte(in); } - /** - * encrypt/decrypt a single byte returning the result. - * - * @param in the byte to be processed. - * @return the result of processing the input byte. - */ - public byte returnByte( - byte in) - { - oneByte[0] = in; - - cipher.processBlock(oneByte, 0, oneByte, 0); - - return oneByte[0]; - } - - /** - * process a block of bytes from in putting the result into out. - * - * @param in the input byte array. - * @param inOff the offset into the in array where the data to be processed starts. - * @param len the number of bytes to be processed. - * @param out the output buffer the processed bytes go into. - * @param outOff the offset into the output byte array the processed data stars at. - * @exception DataLengthException if the output buffer is too small. - */ - public void processBytes( - byte[] in, - int inOff, - int len, - byte[] out, - int outOff) + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { if (outOff + len > out.length) { - throw new DataLengthException("output buffer too small in processBytes()"); + throw new DataLengthException("output buffer too short"); } - for (int i = 0; i != len; i++) + if (inOff + len > in.length) { - cipher.processBlock(in, inOff + i, out, outOff + i); + throw new DataLengthException("input buffer too small"); } + + int inStart = inOff; + int inEnd = inOff + len; + int outStart = outOff; + + while (inStart < inEnd) + { + out[outStart++] = calculateByte(in[inStart++]); + } + + return len; } - /** - * reset the underlying cipher. This leaves it in the same state - * it was at after the last init (if there was one). - */ - public void reset() - { - cipher.reset(); - } -} + protected abstract byte calculateByte(byte b); +} \ No newline at end of file diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamCipher.java index 1ca9a8799..ba3107e3c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/StreamCipher.java @@ -40,9 +40,10 @@ public interface StreamCipher * @param len the number of bytes to be processed. * @param out the output buffer the processed bytes go into. * @param outOff the offset into the output byte array the processed data starts at. + * @return the number of bytes produced - should always be len. * @exception DataLengthException if the output buffer is too small. */ - public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException; /** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java index 7cf2c4faf..e7f1853e3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEParticipant.java @@ -10,19 +10,16 @@ import org.spongycastle.util.Arrays; /** * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange. - * - * + ** The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper * * "Password Authenticated Key Exchange by Juggling, 2008." - *
- * + ** The J-PAKE protocol is symmetric. * There is no notion of a client or server, but rather just two participants. * An instance of {@link JPAKEParticipant} represents one participant, and * is the primary interface for executing the exchange. - *
- * + ** To execute an exchange, construct a {@link JPAKEParticipant} on each end, * and call the following 7 methods * (once and only once, in the given order, for each participant, sending messages between them as described): @@ -35,36 +32,29 @@ import org.spongycastle.util.Arrays; *
* Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}. * The caller is responsible for deriving the session key using a secure key derivation function (KDF). - *
- * + ** Round 3 is an optional key confirmation process. * If you do not execute round 3, then there is no assurance that both participants are using the same key. * (i.e. if the participants used different passwords, then their session keys will differ.) - *
- * + ** If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides. - *
- * + ** The symmetric design can easily support the asymmetric cases when one party initiates the communication. * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass. * Also, in some cases, the key confirmation payload can be sent together with the round2 payload. * These are the trivial techniques to optimize the communication. - *
- * + ** The key confirmation process is implemented as specified in * NIST SP 800-56A Revision 1, * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes. - *
- * + ** This class is stateful and NOT threadsafe. * Each instance should only be used for ONE complete J-PAKE exchange * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange). - *
- * + ** See {@link JPAKEExample} for example usage. */ public class JPAKEParticipant @@ -155,7 +145,7 @@ public class JPAKEParticipant * Convenience constructor for a new {@link JPAKEParticipant} that uses * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group, * a SHA-256 digest, and a default {@link SecureRandom} implementation. - *
+ ** After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. * * @param participantId unique identifier of this participant. @@ -180,7 +170,7 @@ public class JPAKEParticipant /** * Convenience constructor for a new {@link JPAKEParticipant} that uses * a SHA-256 digest and a default {@link SecureRandom} implementation. - *
+ ** After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. * * @param participantId unique identifier of this participant. @@ -209,7 +199,7 @@ public class JPAKEParticipant /** * Construct a new {@link JPAKEParticipant}. - *
+ ** After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. * * @param participantId unique identifier of this participant. @@ -278,8 +268,7 @@ public class JPAKEParticipant /** * Creates and returns the payload to send to the other participant during round 1. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}. */ public JPAKERound1Payload createRound1PayloadToSend() @@ -304,11 +293,9 @@ public class JPAKEParticipant /** * Validates the payload received from the other participant during round 1. - *
- * + ** Must be called prior to {@link #createRound2PayloadToSend()}. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}. * * @throws CryptoException if validation fails. @@ -338,11 +325,9 @@ public class JPAKEParticipant /** * Creates and returns the payload to send to the other participant during round 2. - *
- * + ** {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}. * * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times @@ -370,16 +355,13 @@ public class JPAKEParticipant /** * Validates the payload received from the other participant during round 2. - *
- * + ** Note that this DOES NOT detect a non-common password. * The only indication of a non-common password is through derivation * of different keys (which can be detected explicitly by executing round 3 and round 4) - *
- * + ** Must be called prior to {@link #calculateKeyingMaterial()}. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}. * * @throws CryptoException if validation fails. @@ -412,8 +394,7 @@ public class JPAKEParticipant * Calculates and returns the key material. * A session key must be derived from this key material using a secure key derivation function (KDF). * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}). - *
- * + ** The keying material will be identical for each participant if and only if * each participant's password is the same. i.e. If the participants do not * share the same password, then each participant will derive a different key. @@ -422,17 +403,13 @@ public class JPAKEParticipant * If you want to handle this detection explicitly, you can optionally perform * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute * rounds 3 and 4. - *
- * + ** The keying material will be in the range [0, p-1]. - *
- * + ** {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method. - *
- * + ** As a side effect, the internal {@link #password} array is cleared, since it is no longer needed. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}. * * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)}, @@ -484,11 +461,9 @@ public class JPAKEParticipant /** * Creates and returns the payload to send to the other participant during round 3. - *
- * + ** See {@link JPAKEParticipant} for more details on round 3. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}. * * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}. @@ -522,11 +497,9 @@ public class JPAKEParticipant /** * Validates the payload received from the other participant during round 3. - *
- * + ** See {@link JPAKEParticipant} for more details on round 3. - *
- * + ** After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}. * * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java index 01f82e68c..3571e81b0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java @@ -4,15 +4,12 @@ import java.math.BigInteger; /** * A pre-computed prime order group for use during a J-PAKE exchange. - *
- * + ** Typically a Schnorr group is used. In general, J-PAKE can use any prime order group * that is suitable for public key cryptography, including elliptic curve cryptography. - *
- * + ** See {@link JPAKEPrimeOrderGroups} for convenient standard groups. - *
- * + ** NIST publishes * many groups that can be used for the desired level of security. */ @@ -24,12 +21,10 @@ public class JPAKEPrimeOrderGroup /** * Constructs a new {@link JPAKEPrimeOrderGroup}. - *
- * + ** In general, you should use one of the pre-approved groups from * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one. - *
- * + ** The following basic checks are performed: *
* The prime checks are performed using {@link BigInteger#isProbablePrime(int)}, * and are therefore subject to the same probability guarantees. - *
- * + ** These checks prevent trivial mistakes. * However, due to the small uncertainties if p and q are not prime, * advanced attacks are not prevented. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java index 4cda6f2d4..17f576a04 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java @@ -5,12 +5,10 @@ import java.math.BigInteger; /** * Standard pre-computed prime order groups for use by J-PAKE. * (J-PAKE can use pre-computed prime order groups, same as DSA and Diffie-Hellman.) - *
- * + ** This class contains some convenient constants for use as input for * constructing {@link JPAKEParticipant}s. - *
- * + ** The prime order groups below are taken from Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB), * and from the prime order groups * published by NIST. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java index c5eda2417..0f6d38384 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound1Payload.java @@ -6,19 +6,16 @@ import org.spongycastle.util.Arrays; /** * The payload sent/received during the first round of a J-PAKE exchange. - *
- * + ** Each {@link JPAKEParticipant} creates and sends an instance * of this payload to the other {@link JPAKEParticipant}. * The payload to send should be created via * {@link JPAKEParticipant#createRound1PayloadToSend()}. - *
- * + ** Each {@link JPAKEParticipant} must also validate the payload * received from the other {@link JPAKEParticipant}. * The received payload should be validated via * {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}. - *
*/ public class JPAKERound1Payload { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java index 684d6ccc8..3df5c7b95 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound2Payload.java @@ -6,19 +6,16 @@ import org.spongycastle.util.Arrays; /** * The payload sent/received during the second round of a J-PAKE exchange. - * - * + ** Each {@link JPAKEParticipant} creates and sends an instance * of this payload to the other {@link JPAKEParticipant}. * The payload to send should be created via * {@link JPAKEParticipant#createRound2PayloadToSend()} - *
- * + ** Each {@link JPAKEParticipant} must also validate the payload * received from the other {@link JPAKEParticipant}. * The received payload should be validated via * {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)} - *
*/ public class JPAKERound2Payload { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java index d8ebf9c46..bb4f6e141 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKERound3Payload.java @@ -5,19 +5,16 @@ import java.math.BigInteger; /** * The payload sent/received during the optional third round of a J-PAKE exchange, * which is for explicit key confirmation. - * - * + ** Each {@link JPAKEParticipant} creates and sends an instance * of this payload to the other {@link JPAKEParticipant}. * The payload to send should be created via * {@link JPAKEParticipant#createRound3PayloadToSend(BigInteger)} - *
- * + ** Each {@link JPAKEParticipant} must also validate the payload * received from the other {@link JPAKEParticipant}. * The received payload should be validated via * {@link JPAKEParticipant#validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - *
*/ public class JPAKERound3Payload { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java index aa65ef8ec..39931f4af 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/jpake/JPAKEUtil.java @@ -14,13 +14,11 @@ import org.spongycastle.util.Strings; /** * Primitives needed for a J-PAKE exchange. - * - * + ** The recommended way to perform a J-PAKE exchange is by using * two {@link JPAKEParticipant}s. Internally, those participants * call these primitive operations in {@link JPAKEUtil}. - *
- * + ** The primitives, however, can be used without a {@link JPAKEParticipant} * if needed. */ @@ -31,8 +29,7 @@ public class JPAKEUtil /** * Return a value that can be used as x1 or x3 during round 1. - *
- * + ** The returned value is a random value in the range [0, q-1]. */ public static BigInteger generateX1( @@ -46,8 +43,7 @@ public class JPAKEUtil /** * Return a value that can be used as x2 or x4 during round 1. - *
- * + ** The returned value is a random value in the range [1, q-1]. */ public static BigInteger generateX2( @@ -188,10 +184,9 @@ public class JPAKEUtil /** * Validates that ga is not 1. - *
- * + ** As described by Feng Hao... - *
+ **
* Alice could simply check ga != 1 to ensure it is a generator. * In fact, as we will explain in Section 3, (x1 + x3 + x4 ) is random over Zq even in the face of active attacks. @@ -250,8 +245,6 @@ public class JPAKEUtil * Calculates the keying material, which can be done after round 2 has completed. * A session key must be derived from this key material using a secure key derivation function (KDF). * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}). - * - * ** KeyingMaterial = (B/g^{x2*x4*s})^x2 *@@ -326,8 +319,6 @@ public class JPAKEUtil * Calculates the MacTag (to be used for key confirmation), as defined by * NIST SP 800-56A Revision 1, * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes. - * - * ** MacTag = HMAC(MacKey, MacLen, MacData) * @@ -339,10 +330,9 @@ public class JPAKEUtil * is always the initiator for key confirmation. * * HMAC = {@link HMac} used with the given {@link Digest} - * H = The given {@link Digest} + * H = The given {@link Digest} * MacLen = length of MacTag *- * */ public static BigInteger calculateMacTag( String participantId, @@ -383,8 +373,6 @@ public class JPAKEUtil /** * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation). - * - * ** MacKey = H(K || "JPAKE_KC") *@@ -407,7 +395,6 @@ public class JPAKEUtil /** * Validates the MacTag received from the partner participant. - * * * @param partnerMacTag the MacTag received from the partner. * @throws CryptoException if the participantId strings are equal. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java index 96656cedf..5f3f4c520 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKDFParameters.java @@ -1,7 +1,6 @@ package org.spongycastle.crypto.agreement.kdf; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.crypto.DerivationParameters; public class DHKDFParameters @@ -13,7 +12,7 @@ public class DHKDFParameters private byte[] extraInfo; public DHKDFParameters( - DERObjectIdentifier algorithm, + ASN1ObjectIdentifier algorithm, int keySize, byte[] z) { @@ -21,12 +20,12 @@ public class DHKDFParameters } public DHKDFParameters( - DERObjectIdentifier algorithm, + ASN1ObjectIdentifier algorithm, int keySize, byte[] z, byte[] extraInfo) { - this.algorithm = new ASN1ObjectIdentifier(algorithm.getId()); + this.algorithm = algorithm; this.keySize = keySize; this.z = z; this.extraInfo = extraInfo; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java index 6d27a9db7..70cf630d7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/DHKEKGenerator.java @@ -4,7 +4,7 @@ import java.io.IOException; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERTaggedObject; @@ -12,7 +12,7 @@ import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.DerivationFunction; import org.spongycastle.crypto.DerivationParameters; import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * RFC 2631 Diffie-hellman KEK derivation function. @@ -22,7 +22,7 @@ public class DHKEKGenerator { private final Digest digest; - private DERObjectIdentifier algorithm; + private ASN1ObjectIdentifier algorithm; private int keySize; private byte[] z; private byte[] partyAInfo; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java index d427f9895..65c564e8b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/kdf/ECDHKEKGenerator.java @@ -16,7 +16,7 @@ import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.DigestDerivationFunction; import org.spongycastle.crypto.generators.KDF2BytesGenerator; import org.spongycastle.crypto.params.KDFParameters; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * X9.63 based key derivation function for ECDH CMS. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java index d47ad39ec..c6ee4dbee 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Client.java @@ -25,6 +25,10 @@ public class SRP6Client protected BigInteger u; protected BigInteger S; + protected BigInteger M1; + protected BigInteger M2; + protected BigInteger Key; + protected Digest digest; protected SecureRandom random; @@ -64,7 +68,7 @@ public class SRP6Client } /** - * Generates client's verification message given the server's credentials + * Generates the secret S given the server's credentials * @param serverB The server's credentials * @return Client's verification message for the server * @throws CryptoException If server's credentials are invalid @@ -90,4 +94,57 @@ public class SRP6Client BigInteger tmp = g.modPow(x, N).multiply(k).mod(N); return B.subtract(tmp).mod(N).modPow(exp, N); } + + /** + * Computes the client evidence message M1 using the previously received values. + * To be called after calculating the secret S. + * @return M1: the client side generated evidence message + * @throws CryptoException + */ + public BigInteger calculateClientEvidenceMessage() throws CryptoException{ + // verify pre-requirements + if ((this.A==null)||(this.B==null)||(this.S==null)){ + throw new CryptoException("Impossible to compute M1: " + + "some data are missing from the previous operations (A,B,S)"); + } + // compute the client evidence message 'M1' + this.M1 = SRP6Util.calculateM1(digest, N, A, B, S); + return M1; + } + + /** Authenticates the server evidence message M2 received and saves it only if correct. + * @param M2: the server side generated evidence message + * @return A boolean indicating if the server message M2 was the expected one. + * @throws CryptoException + */ + public boolean verifyServerEvidenceMessage(BigInteger serverM2) throws CryptoException{ + //verify pre-requirements + if ((this.A==null)||(this.M1==null)||(this.S==null)){ + throw new CryptoException("Impossible to compute and verify M2: " + + "some data are missing from the previous operations (A,M1,S)"); + } + // Compute the own server evidence message 'M2' + BigInteger computedM2 = SRP6Util.calculateM2(digest, N, A, M1, S); + if (computedM2.equals(serverM2)){ + this.M2 = serverM2; + return true; + } + return false; + } + + /** + * Computes the final session key as a result of the SRP successful mutual authentication + * To be called after verifying the server evidence message M2. + * @return Key: the mutually authenticated symmetric session key + * @throws CryptoException + */ + public BigInteger calculateSessionKey() throws CryptoException{ + //verify pre-requirements (here we enforce a previous calculation of M1 and M2) + if ((this.S==null)||(this.M1==null)||(this.M2==null)){ + throw new CryptoException("Impossible to compute Key: " + + "some data are missing from the previous operations (S,M1,M2)"); + } + this.Key = SRP6Util.calculateKey(digest, N, S); + return Key; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java index 50f6f7cea..efbdd0abe 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Server.java @@ -27,7 +27,10 @@ public class SRP6Server protected BigInteger u; protected BigInteger S; - + protected BigInteger M1; + protected BigInteger M2; + protected BigInteger Key; + public SRP6Server() { } @@ -87,4 +90,59 @@ public class SRP6Server { return v.modPow(u, N).multiply(A).mod(N).modPow(b, N); } + + /** + * Authenticates the received client evidence message M1 and saves it only if correct. + * To be called after calculating the secret S. + * @param M1: the client side generated evidence message + * @return A boolean indicating if the client message M1 was the expected one. + * @throws CryptoException + */ + public boolean verifyClientEvidenceMessage(BigInteger clientM1) throws CryptoException{ + //verify pre-requirements + if ((this.A==null)||(this.B==null)||(this.S==null)){ + throw new CryptoException("Impossible to compute and verify M1: " + + "some data are missing from the previous operations (A,B,S)"); + } + // Compute the own client evidence message 'M1' + BigInteger computedM1 = SRP6Util.calculateM1(digest, N, A, B, S); + if (computedM1.equals(clientM1)){ + this.M1 = clientM1; + return true; + } + return false; + } + + /** + * Computes the server evidence message M2 using the previously verified values. + * To be called after successfully verifying the client evidence message M1. + * @return M2: the server side generated evidence message + * @throws CryptoException + */ + public BigInteger calculateServerEvidenceMessage() throws CryptoException{ + //verify pre-requirements + if ((this.A==null)||(this.M1==null)||(this.S==null)){ + throw new CryptoException("Impossible to compute M2: " + + "some data are missing from the previous operations (A,M1,S)"); + } + // Compute the server evidence message 'M2' + this.M2 = SRP6Util.calculateM2(digest, N, A, M1, S); + return M2; + } + + /** + * Computes the final session key as a result of the SRP successful mutual authentication + * To be called after calculating the server evidence message M2. + * @return Key: the mutual authenticated symmetric session key + * @throws CryptoException + */ + public BigInteger calculateSessionKey() throws CryptoException{ + //verify pre-requirements + if ((this.S==null)||(this.M1==null)||(this.M2==null)){ + throw new CryptoException("Impossible to compute Key: " + + "some data are missing from the previous operations (S,M1,M2)"); + } + this.Key = SRP6Util.calculateKey(digest, N, S); + return Key; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java index 40ec01c0f..25d5b9a74 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/agreement/srp/SRP6Util.java @@ -60,6 +60,69 @@ public class SRP6Util return val; } + /** + * Computes the client evidence message (M1) according to the standard routine: + * M1 = H( A | B | S ) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param A The public client value + * @param B The public server value + * @param S The secret calculated by both sides + * @return M1 The calculated client evidence message + */ + public static BigInteger calculateM1(Digest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S) { + BigInteger M1 = hashPaddedTriplet(digest,N,A,B,S); + return M1; + } + + /** + * Computes the server evidence message (M2) according to the standard routine: + * M2 = H( A | M1 | S ) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param A The public client value + * @param M1 The client evidence message + * @param S The secret calculated by both sides + * @return M2 The calculated server evidence message + */ + public static BigInteger calculateM2(Digest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S){ + BigInteger M2 = hashPaddedTriplet(digest,N,A,M1,S); + return M2; + } + + /** + * Computes the final Key according to the standard routine: Key = H(S) + * @param digest The Digest used as the hashing function H + * @param N Modulus used to get the pad length + * @param S The secret calculated by both sides + * @return + */ + public static BigInteger calculateKey(Digest digest, BigInteger N, BigInteger S) { + int padLength = (N.bitLength() + 7) / 8; + byte[] _S = getPadded(S,padLength); + digest.update(_S, 0, _S.length); + + byte[] output = new byte[digest.getDigestSize()]; + digest.doFinal(output, 0); + return new BigInteger(1, output); + } + + private static BigInteger hashPaddedTriplet(Digest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3){ + int padLength = (N.bitLength() + 7) / 8; + + byte[] n1_bytes = getPadded(n1, padLength); + byte[] n2_bytes = getPadded(n2, padLength); + byte[] n3_bytes = getPadded(n3, padLength); + + digest.update(n1_bytes, 0, n1_bytes.length); + digest.update(n2_bytes, 0, n2_bytes.length); + digest.update(n3_bytes, 0, n3_bytes.length); + + byte[] output = new byte[digest.getDigestSize()]; + digest.doFinal(output, 0); + + return new BigInteger(1, output); + } private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java new file mode 100644 index 000000000..643df2f8f --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/EncodableDigest.java @@ -0,0 +1,17 @@ +package org.spongycastle.crypto.digests; + +/** + * Encodable digests allow you to download an encoded copy of their internal state. This is useful for the situation where + * you need to generate a signature on an external device and it allows for "sign with last round", so a copy of the + * internal state of the digest, plus the last few blocks of the message are all that needs to be sent, rather than the + * entire message. + */ +public interface EncodableDigest +{ + /** + * Return an encoded byte array for the digest's internal state + * + * @return an encoding of the digests internal state. + */ + byte[] getEncodedState(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java index a540c99f2..e5473cf01 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GOST3411Digest.java @@ -5,9 +5,9 @@ import org.spongycastle.crypto.ExtendedDigest; import org.spongycastle.crypto.engines.GOST28147Engine; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithSBox; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** * implementation of GOST R 34.11-94 diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java index b7c53336d..e83bc9915 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/GeneralDigest.java @@ -2,6 +2,7 @@ package org.spongycastle.crypto.digests; import org.spongycastle.crypto.ExtendedDigest; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** * base implementation of MD4 family style digest as outlined in @@ -11,8 +12,9 @@ public abstract class GeneralDigest implements ExtendedDigest, Memoable { private static final int BYTE_LENGTH = 64; - private byte[] xBuf; - private int xBufOff; + + private final byte[] xBuf = new byte[4]; + private int xBufOff; private long byteCount; @@ -21,7 +23,6 @@ public abstract class GeneralDigest */ protected GeneralDigest() { - xBuf = new byte[4]; xBufOff = 0; } @@ -32,11 +33,16 @@ public abstract class GeneralDigest */ protected GeneralDigest(GeneralDigest t) { - xBuf = new byte[t.xBuf.length]; - copyIn(t); } + protected GeneralDigest(byte[] encodedState) + { + System.arraycopy(encodedState, 0, xBuf, 0, xBuf.length); + xBufOff = Pack.bigEndianToInt(encodedState, 4); + byteCount = Pack.bigEndianToLong(encodedState, 8); + } + protected void copyIn(GeneralDigest t) { System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); @@ -129,6 +135,13 @@ public abstract class GeneralDigest } } + protected void populateState(byte[] state) + { + System.arraycopy(xBuf, 0, state, 0, xBufOff); + Pack.intToBigEndian(xBufOff, state, 4); + Pack.longToBigEndian(byteCount, state, 8); + } + public int getByteLength() { return BYTE_LENGTH; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java index 0e4040add..50a9b6648 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/LongDigest.java @@ -1,18 +1,18 @@ package org.spongycastle.crypto.digests; import org.spongycastle.crypto.ExtendedDigest; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** * Base class for SHA-384 and SHA-512. */ public abstract class LongDigest - implements ExtendedDigest, Memoable + implements ExtendedDigest, Memoable, EncodableDigest { private static final int BYTE_LENGTH = 128; - - private byte[] xBuf; + + private byte[] xBuf = new byte[8]; private int xBufOff; private long byteCount1; @@ -28,7 +28,6 @@ public abstract class LongDigest */ protected LongDigest() { - xBuf = new byte[8]; xBufOff = 0; reset(); @@ -41,8 +40,6 @@ public abstract class LongDigest */ protected LongDigest(LongDigest t) { - xBuf = new byte[t.xBuf.length]; - copyIn(t); } @@ -67,6 +64,56 @@ public abstract class LongDigest wOff = t.wOff; } + protected void populateState(byte[] state) + { + System.arraycopy(xBuf, 0, state, 0, xBufOff); + Pack.intToBigEndian(xBufOff, state, 8); + Pack.longToBigEndian(byteCount1, state, 12); + Pack.longToBigEndian(byteCount2, state, 20); + Pack.longToBigEndian(H1, state, 28); + Pack.longToBigEndian(H2, state, 36); + Pack.longToBigEndian(H3, state, 44); + Pack.longToBigEndian(H4, state, 52); + Pack.longToBigEndian(H5, state, 60); + Pack.longToBigEndian(H6, state, 68); + Pack.longToBigEndian(H7, state, 76); + Pack.longToBigEndian(H8, state, 84); + + Pack.intToBigEndian(wOff, state, 92); + for (int i = 0; i < wOff; i++) + { + Pack.longToBigEndian(W[i], state, 96 + (i * 8)); + } + } + + protected void restoreState(byte[] encodedState) + { + xBufOff = Pack.bigEndianToInt(encodedState, 8); + System.arraycopy(encodedState, 0, xBuf, 0, xBufOff); + byteCount1 = Pack.bigEndianToLong(encodedState, 12); + byteCount2 = Pack.bigEndianToLong(encodedState, 20); + + H1 = Pack.bigEndianToLong(encodedState, 28); + H2 = Pack.bigEndianToLong(encodedState, 36); + H3 = Pack.bigEndianToLong(encodedState, 44); + H4 = Pack.bigEndianToLong(encodedState, 52); + H5 = Pack.bigEndianToLong(encodedState, 60); + H6 = Pack.bigEndianToLong(encodedState, 68); + H7 = Pack.bigEndianToLong(encodedState, 76); + H8 = Pack.bigEndianToLong(encodedState, 84); + + wOff = Pack.bigEndianToInt(encodedState, 92); + for (int i = 0; i < wOff; i++) + { + W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8)); + } + } + + protected int getEncodedStateSize() + { + return 96 + (wOff * 8); + } + public void update( byte in) { @@ -165,7 +212,7 @@ public abstract class LongDigest { return BYTE_LENGTH; } - + protected void processWord( byte[] in, int inOff) @@ -228,7 +275,7 @@ public abstract class LongDigest long g = H7; long h = H8; - int t = 0; + int t = 0; for(int i = 0; i < 10; i ++) { // t = 8 * i @@ -271,7 +318,7 @@ public abstract class LongDigest e += a; a += Sum0(b) + Maj(b, c, d); } - + H1 += a; H2 += b; H3 += c; @@ -358,4 +405,5 @@ public abstract class LongDigest 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL, 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L }; + } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java index cc63dcdfa..57df0c1e2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA1Digest.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. @@ -11,6 +11,7 @@ import org.spongycastle.util.Memoable; */ public class SHA1Digest extends GeneralDigest + implements EncodableDigest { private static final int DIGEST_LENGTH = 20; @@ -38,6 +39,23 @@ public class SHA1Digest copyIn(t); } + public SHA1Digest(byte[] encodedState) + { + super(encodedState); + + H1 = Pack.bigEndianToInt(encodedState, 16); + H2 = Pack.bigEndianToInt(encodedState, 20); + H3 = Pack.bigEndianToInt(encodedState, 24); + H4 = Pack.bigEndianToInt(encodedState, 28); + H5 = Pack.bigEndianToInt(encodedState, 32); + + xOff = Pack.bigEndianToInt(encodedState, 36); + for (int i = 0; i != xOff; i++) + { + X[i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4)); + } + } + private void copyIn(SHA1Digest t) { H1 = t.H1; @@ -302,6 +320,27 @@ public class SHA1Digest super.copyIn(d); copyIn(d); } + + public byte[] getEncodedState() + { + byte[] state = new byte[40 + xOff * 4]; + + super.populateState(state); + + Pack.intToBigEndian(H1, state, 16); + Pack.intToBigEndian(H2, state, 20); + Pack.intToBigEndian(H3, state, 24); + Pack.intToBigEndian(H4, state, 28); + Pack.intToBigEndian(H5, state, 32); + Pack.intToBigEndian(xOff, state, 36); + + for (int i = 0; i != xOff; i++) + { + Pack.intToBigEndian(X[i], state, 40 + (i * 4)); + } + + return state; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java index 4a0063b42..e542e996a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA224Digest.java @@ -1,8 +1,8 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** @@ -18,6 +18,7 @@ import org.spongycastle.util.Memoable; */ public class SHA224Digest extends GeneralDigest + implements EncodableDigest { private static final int DIGEST_LENGTH = 28; @@ -62,6 +63,26 @@ public class SHA224Digest xOff = t.xOff; } + public SHA224Digest(byte[] encodedState) + { + super(encodedState); + + H1 = Pack.bigEndianToInt(encodedState, 16); + H2 = Pack.bigEndianToInt(encodedState, 20); + H3 = Pack.bigEndianToInt(encodedState, 24); + H4 = Pack.bigEndianToInt(encodedState, 28); + H5 = Pack.bigEndianToInt(encodedState, 32); + H6 = Pack.bigEndianToInt(encodedState, 36); + H7 = Pack.bigEndianToInt(encodedState, 40); + H8 = Pack.bigEndianToInt(encodedState, 44); + + xOff = Pack.bigEndianToInt(encodedState, 48); + for (int i = 0; i != xOff; i++) + { + X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4)); + } + } + public String getAlgorithmName() { return "SHA-224"; @@ -307,5 +328,29 @@ public class SHA224Digest doCopy(d); } + + public byte[] getEncodedState() + { + byte[] state = new byte[52 + xOff * 4]; + + super.populateState(state); + + Pack.intToBigEndian(H1, state, 16); + Pack.intToBigEndian(H2, state, 20); + Pack.intToBigEndian(H3, state, 24); + Pack.intToBigEndian(H4, state, 28); + Pack.intToBigEndian(H5, state, 32); + Pack.intToBigEndian(H6, state, 36); + Pack.intToBigEndian(H7, state, 40); + Pack.intToBigEndian(H8, state, 44); + Pack.intToBigEndian(xOff, state, 48); + + for (int i = 0; i != xOff; i++) + { + Pack.intToBigEndian(X[i], state, 52 + (i * 4)); + } + + return state; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java index f14c50ae6..9fe183479 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA256Digest.java @@ -1,8 +1,8 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** @@ -18,6 +18,7 @@ import org.spongycastle.util.Memoable; */ public class SHA256Digest extends GeneralDigest + implements EncodableDigest { private static final int DIGEST_LENGTH = 32; @@ -62,6 +63,27 @@ public class SHA256Digest xOff = t.xOff; } + public SHA256Digest(byte[] encodedState) + { + super(encodedState); + + H1 = Pack.bigEndianToInt(encodedState, 16); + H2 = Pack.bigEndianToInt(encodedState, 20); + H3 = Pack.bigEndianToInt(encodedState, 24); + H4 = Pack.bigEndianToInt(encodedState, 28); + H5 = Pack.bigEndianToInt(encodedState, 32); + H6 = Pack.bigEndianToInt(encodedState, 36); + H7 = Pack.bigEndianToInt(encodedState, 40); + H8 = Pack.bigEndianToInt(encodedState, 44); + + xOff = Pack.bigEndianToInt(encodedState, 48); + for (int i = 0; i != xOff; i++) + { + X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4)); + } + } + + public String getAlgorithmName() { return "SHA-256"; @@ -310,5 +332,29 @@ public class SHA256Digest copyIn(d); } + + public byte[] getEncodedState() + { + byte[] state = new byte[52 + xOff * 4]; + + super.populateState(state); + + Pack.intToBigEndian(H1, state, 16); + Pack.intToBigEndian(H2, state, 20); + Pack.intToBigEndian(H3, state, 24); + Pack.intToBigEndian(H4, state, 28); + Pack.intToBigEndian(H5, state, 32); + Pack.intToBigEndian(H6, state, 36); + Pack.intToBigEndian(H7, state, 40); + Pack.intToBigEndian(H8, state, 44); + Pack.intToBigEndian(xOff, state, 48); + + for (int i = 0; i != xOff; i++) + { + Pack.intToBigEndian(X[i], state, 52 + (i * 4)); + } + + return state; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java index f6a5ba0a8..1bf7c6ade 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA384Digest.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** @@ -36,6 +36,11 @@ public class SHA384Digest super(t); } + public SHA384Digest(byte[] encodedState) + { + restoreState(encodedState); + } + public String getAlgorithmName() { return "SHA-384"; @@ -96,4 +101,11 @@ public class SHA384Digest super.copyIn(d); } + + public byte[] getEncodedState() + { + byte[] encoded = new byte[getEncodedStateSize()]; + super.populateState(encoded); + return encoded; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java index 3416b7139..936e29b9c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java @@ -5,7 +5,7 @@ import org.spongycastle.util.Arrays; /** * implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ - * + ** Following the naming conventions used in the C source code to enable easy review of the implementation. */ public class SHA3Digest diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java index 2fd3711d5..f97b12309 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512Digest.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** @@ -36,6 +36,11 @@ public class SHA512Digest super(t); } + public SHA512Digest(byte[] encodedState) + { + restoreState(encodedState); + } + public String getAlgorithmName() { return "SHA-512"; @@ -98,5 +103,12 @@ public class SHA512Digest copyIn(d); } + + public byte[] getEncodedState() + { + byte[] encoded = new byte[getEncodedStateSize()]; + super.populateState(encoded); + return encoded; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java index c6d2dd767..fc05781f8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA512tDigest.java @@ -2,6 +2,7 @@ package org.spongycastle.crypto.digests; import org.spongycastle.util.Memoable; import org.spongycastle.util.MemoableResetException; +import org.spongycastle.util.Pack; /** * FIPS 180-4 implementation of SHA-512/t @@ -9,7 +10,7 @@ import org.spongycastle.util.MemoableResetException; public class SHA512tDigest extends LongDigest { - private final int digestLength; + private int digestLength; // non-final due to old flow analyser. private long H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t; @@ -53,6 +54,17 @@ public class SHA512tDigest reset(t); } + public SHA512tDigest(byte[] encodedState) + { + this(readDigestLength(encodedState)); + restoreState(encodedState); + } + + private static int readDigestLength(byte[] encodedState) + { + return Pack.bigEndianToInt(encodedState, encodedState.length - 4); + } + public String getAlgorithmName() { return "SHA-512/" + Integer.toString(digestLength * 8); @@ -202,4 +214,14 @@ public class SHA512tDigest this.H7t = t.H7t; this.H8t = t.H8t; } + + public byte[] getEncodedState() + { + final int baseSize = getEncodedStateSize(); + byte[] encoded = new byte[baseSize + 4]; + populateState(encoded); + Pack.intToBigEndian(digestLength * 8, encoded, baseSize); + return encoded; + } + } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java index b7117a22d..ed74ba8ef 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SM3Digest.java @@ -1,13 +1,13 @@ package org.spongycastle.crypto.digests; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Memoable; +import org.spongycastle.util.Pack; /** * Implementation of Chinese SM3 digest as described at * http://tools.ietf.org/html/draft-shen-sm3-hash-00 * and at .... ( Chinese PDF ) - *
+ ** The specification says "process a bit stream", * but this is written to process bytes in blocks of 4, * meaning this will process 32-bit word groups. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java index 4da4d7189..d476170ff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinDigest.java @@ -8,13 +8,12 @@ import org.spongycastle.util.Memoable; /** * Implementation of the Skein parameterised hash function in 256, 512 and 1024 bit block sizes, * based on the {@link ThreefishEngine Threefish} tweakable block cipher. - *
+ ** This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3 * competition in October 2010. - *
+ ** Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker. - *
* * @see SkeinEngine * @see SkeinParameters diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java index 001adcf26..12d06d8a2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SkeinEngine.java @@ -14,18 +14,18 @@ import org.spongycastle.util.Memoable; /** * Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block * sizes, based on the {@link ThreefishEngine Threefish} tweakable block cipher. - * + ** This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3 * competition in October 2010. - *
+ ** Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker. - *
+ ** This implementation is the basis for {@link SkeinDigest} and {@link SkeinMac}, implementing the * parameter based configuration system that allows Skein to be adapted to multiple applications.
+ *
* Initialising the engine with {@link SkeinParameters} allows standard and arbitrary parameters to * be applied during the Skein hash function. - ** Implemented: *
*
- * + *- 256, 512 and 1024 bit internal states.
@@ -34,7 +34,7 @@ import org.spongycastle.util.Memoable; * parameters. *- Arbitrary output size in 1 byte intervals.
** Not implemented: *
*
*- Sub-byte length input (bit padding).
diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java new file mode 100644 index 000000000..f2735a8c6 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/CustomNamedCurves.java @@ -0,0 +1,320 @@ +package org.spongycastle.crypto.ec; + +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Hashtable; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.sec.SECObjectIdentifiers; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.asn1.x9.X9ECParametersHolder; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.custom.djb.Curve25519; +import org.spongycastle.math.ec.custom.sec.SecP192K1Curve; +import org.spongycastle.math.ec.custom.sec.SecP192R1Curve; +import org.spongycastle.math.ec.custom.sec.SecP224K1Curve; +import org.spongycastle.math.ec.custom.sec.SecP224R1Curve; +import org.spongycastle.math.ec.custom.sec.SecP256K1Curve; +import org.spongycastle.math.ec.custom.sec.SecP256R1Curve; +import org.spongycastle.math.ec.custom.sec.SecP384R1Curve; +import org.spongycastle.math.ec.custom.sec.SecP521R1Curve; +import org.spongycastle.math.ec.endo.GLVTypeBEndomorphism; +import org.spongycastle.math.ec.endo.GLVTypeBParameters; +import org.spongycastle.util.Strings; +import org.spongycastle.util.encoders.Hex; + +public class CustomNamedCurves +{ + private static ECCurve configureCurve(ECCurve curve) + { + return curve; + } + + private static ECCurve configureCurveGLV(ECCurve c, GLVTypeBParameters p) + { + return c.configure().setEndomorphism(new GLVTypeBEndomorphism(c, p)).create(); + } + + /* + * curve25519 + */ + static X9ECParametersHolder curve25519 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = null; + ECCurve curve = configureCurve(new Curve25519()); + + /* + * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form + * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3). + * + * The Curve25519 paper doesn't say which of the two possible y values the base + * point has. The choice here is guided by language in the Ed25519 paper. + * + * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14) + */ + ECPoint G = curve.decodePoint(Hex.decode("04" + + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A" + + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9")); + + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp192k1 + */ + static X9ECParametersHolder secp192k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = null; + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16), + new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16), + new BigInteger[]{ + new BigInteger("71169be7330b3038edb025f1", 16), + new BigInteger("-b3fb3400dec5c4adceb8655c", 16) }, + new BigInteger[]{ + new BigInteger("12511cfe811d0f4e6bc688b4d", 16), + new BigInteger("71169be7330b3038edb025f1", 16) }, + new BigInteger("71169be7330b3038edb025f1d0f9", 16), + new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16), + 208); + ECCurve curve = configureCurveGLV(new SecP192K1Curve(), glv); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" + + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp192r1 + */ + static X9ECParametersHolder secp192r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); + ECCurve curve = configureCurve(new SecP192R1Curve()); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" + + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp224k1 + */ + static X9ECParametersHolder secp224k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = null; + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16), + new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16), + new BigInteger[]{ + new BigInteger("6b8cf07d4ca75c88957d9d670591", 16), + new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) }, + new BigInteger[]{ + new BigInteger("1243ae1b4d71613bc9f780a03690e", 16), + new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) }, + new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16), + new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16), + 240); + ECCurve curve = configureCurveGLV(new SecP224K1Curve(), glv); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C" + + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp224r1 + */ + static X9ECParametersHolder secp224r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); + ECCurve curve = configureCurve(new SecP224R1Curve()); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" + + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp256k1 + */ + static X9ECParametersHolder secp256k1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = null; + GLVTypeBParameters glv = new GLVTypeBParameters( + new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16), + new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16), + new BigInteger[]{ + new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16), + new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) }, + new BigInteger[]{ + new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16), + new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) }, + new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16), + new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16), + 272); + ECCurve curve = configureCurveGLV(new SecP256K1Curve(), glv); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp256r1 + */ + static X9ECParametersHolder secp256r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); + ECCurve curve = configureCurve(new SecP256R1Curve()); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp384r1 + */ + static X9ECParametersHolder secp384r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73"); + ECCurve curve = configureCurve(new SecP384R1Curve()); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" + + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + /* + * secp521r1 + */ + static X9ECParametersHolder secp521r1 = new X9ECParametersHolder() + { + protected X9ECParameters createParameters() + { + byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA"); + ECCurve curve = configureCurve(new SecP521R1Curve()); + ECPoint G = curve.decodePoint(Hex.decode("04" + + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" + + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650")); + return new X9ECParameters(curve, G, curve.getOrder(), curve.getCofactor(), S); + } + }; + + static final Hashtable nameToCurve = new Hashtable(); + static final Hashtable nameToOID = new Hashtable(); + static final Hashtable oidToCurve = new Hashtable(); + static final Hashtable oidToName = new Hashtable(); + + static void defineCurve(String name, X9ECParametersHolder holder) + { + nameToCurve.put(name, holder); + } + + static void defineCurveWithOID(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) + { + nameToCurve.put(name, holder); + nameToOID.put(name, oid); + oidToName.put(oid, name); + oidToCurve.put(oid, holder); + } + + static void defineCurveAlias(String alias, ASN1ObjectIdentifier oid) + { + alias = Strings.toLowerCase(alias); + nameToOID.put(alias, oid); + nameToCurve.put(alias, oidToCurve.get(oid)); + } + + static + { + defineCurve("curve25519", curve25519); + + defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1); + defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1); + defineCurveWithOID("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1); + defineCurveWithOID("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1); + defineCurveWithOID("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1); + defineCurveWithOID("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1); + defineCurveWithOID("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1); + defineCurveWithOID("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1); + + defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1); + defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1); + defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1); + defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1); + defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1); + } + + public static X9ECParameters getByName(String name) + { + X9ECParametersHolder holder = (X9ECParametersHolder)nameToCurve.get(Strings.toLowerCase(name)); + return holder == null ? null : holder.getParameters(); + } + + /** + * return the X9ECParameters object for the named curve represented by the passed in object + * identifier. Null if the curve isn't present. + * + * @param oid + * an object identifier representing a named curve, if present. + */ + public static X9ECParameters getByOID(ASN1ObjectIdentifier oid) + { + X9ECParametersHolder holder = (X9ECParametersHolder)oidToCurve.get(oid); + return holder == null ? null : holder.getParameters(); + } + + /** + * return the object identifier signified by the passed in name. Null if there is no object + * identifier associated with name. + * + * @return the object identifier associated with name, if present. + */ + public static ASN1ObjectIdentifier getOID(String name) + { + return (ASN1ObjectIdentifier)nameToOID.get(Strings.toLowerCase(name)); + } + + /** + * return the named curve name represented by the given object identifier. + */ + public static String getName(ASN1ObjectIdentifier oid) + { + return (String)oidToName.get(oid); + } + + /** + * returns an enumeration containing the name strings for curves contained in this structure. + */ + public static Enumeration getNames() + { + return nameToCurve.keys(); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java index 31bd6381c..5359d98f4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalDecryptor.java @@ -43,6 +43,6 @@ public class ECElGamalDecryptor ECPoint tmp = pair.getX().multiply(key.getD()); - return pair.getY().add(tmp.negate()).normalize(); + return pair.getY().subtract(tmp).normalize(); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java index c31a4308b..505fd502f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECElGamalEncryptor.java @@ -4,9 +4,12 @@ import java.math.BigInteger; import java.security.SecureRandom; import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; /** * this does your basic ElGamal encryption algorithm using EC @@ -61,13 +64,23 @@ public class ECElGamalEncryptor throw new IllegalStateException("ECElGamalEncryptor not initialised"); } - BigInteger n = key.getParameters().getN(); - BigInteger k = ECUtil.generateK(n, random); + ECDomainParameters ec = key.getParameters(); + BigInteger k = ECUtil.generateK(ec.getN(), random); - ECPoint g = key.getParameters().getG(); - ECPoint gamma = g.multiply(k); - ECPoint phi = key.getQ().multiply(k).add(point); + ECMultiplier basePointMultiplier = createBasePointMultiplier(); - return new ECPair(gamma.normalize(), phi.normalize()); + ECPoint[] gamma_phi = new ECPoint[]{ + basePointMultiplier.multiply(ec.getG(), k), + key.getQ().multiply(k).add(point) + }; + + ec.getCurve().normalizeAll(gamma_phi); + + return new ECPair(gamma_phi[0], gamma_phi[1]); + } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java index 7b35f1a10..9bd5162bf 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECFixedTransform.java @@ -3,8 +3,11 @@ package org.spongycastle.crypto.ec; import java.math.BigInteger; import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; /** * this transforms the original randomness used for an ElGamal encryption by a fixed value. @@ -38,7 +41,7 @@ public class ECFixedTransform } /** - * Transform an existing cipher test pair using the ElGamal algorithm. Note: it is assumed this + * Transform an existing cipher text pair using the ElGamal algorithm. Note: it is assumed this * transform has been initialised with the same public key that was used to create the original * cipher text. * @@ -52,11 +55,20 @@ public class ECFixedTransform throw new IllegalStateException("ECFixedTransform not initialised"); } - ECPoint g = key.getParameters().getG(); - ECPoint gamma = g.multiply(k); - ECPoint phi = key.getQ().multiply(k).add(cipherText.getY()); + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); - return new ECPair(cipherText.getX().add(gamma).normalize(), phi.normalize()); + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + BigInteger k = this.k.mod(n); + + ECPoint[] gamma_phi = new ECPoint[]{ + basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()), + key.getQ().multiply(k).add(cipherText.getY()) + }; + + ec.getCurve().normalizeAll(gamma_phi); + + return new ECPair(gamma_phi[0], gamma_phi[1]); } /** @@ -68,4 +80,9 @@ public class ECFixedTransform { return k; } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java index d8b1203b5..a1d67fa90 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewPublicKeyTransform.java @@ -4,9 +4,12 @@ import java.math.BigInteger; import java.security.SecureRandom; import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; /** * this does your basic Elgamal encryption algorithm using EC @@ -49,7 +52,7 @@ public class ECNewPublicKeyTransform } /** - * Transform an existing cipher test pair using the ElGamal algorithm. Note: the input cipherText will + * Transform an existing cipher text pair using the ElGamal algorithm. Note: the input cipherText will * need to be preserved in order to complete the transformation to the new public key. * * @param cipherText the EC point to process. @@ -62,13 +65,24 @@ public class ECNewPublicKeyTransform throw new IllegalStateException("ECNewPublicKeyTransform not initialised"); } - BigInteger n = key.getParameters().getN(); - BigInteger k = ECUtil.generateK(n, random); + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); - ECPoint g = key.getParameters().getG(); - ECPoint gamma = g.multiply(k); - ECPoint phi = key.getQ().multiply(k).add(cipherText.getY()); + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + BigInteger k = ECUtil.generateK(n, random); - return new ECPair(gamma.normalize(), phi.normalize()); + ECPoint[] gamma_phi = new ECPoint[]{ + basePointMultiplier.multiply(ec.getG(), k), + key.getQ().multiply(k).add(cipherText.getY()) + }; + + ec.getCurve().normalizeAll(gamma_phi); + + return new ECPair(gamma_phi[0], gamma_phi[1]); + } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java index 9b70fc467..0f689d4d8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECNewRandomnessTransform.java @@ -4,9 +4,12 @@ import java.math.BigInteger; import java.security.SecureRandom; import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; /** * this transforms the original randomness used for an ElGamal encryption. @@ -66,16 +69,23 @@ public class ECNewRandomnessTransform throw new IllegalStateException("ECNewRandomnessTransform not initialised"); } - BigInteger n = key.getParameters().getN(); - BigInteger k = ECUtil.generateK(n, random); - ECPoint g = key.getParameters().getG(); - ECPoint gamma = g.multiply(k); - ECPoint phi = key.getQ().multiply(k).add(cipherText.getY()); + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); + + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + BigInteger k = ECUtil.generateK(n, random); + + ECPoint[] gamma_phi = new ECPoint[]{ + basePointMultiplier.multiply(ec.getG(), k).add(cipherText.getX()), + key.getQ().multiply(k).add(cipherText.getY()) + }; + + ec.getCurve().normalizeAll(gamma_phi); lastK = k; - return new ECPair(cipherText.getX().add(gamma).normalize(), phi.normalize()); + return new ECPair(gamma_phi[0], gamma_phi[1]); } /** @@ -87,4 +97,9 @@ public class ECNewRandomnessTransform { return lastK; } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java index 00f9a2b79..cbfaaaa68 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/ec/ECUtil.java @@ -9,14 +9,13 @@ class ECUtil { static BigInteger generateK(BigInteger n, SecureRandom random) { - int nBitLength = n.bitLength(); - BigInteger k = new BigInteger(nBitLength, random); - - while (k.equals(ECConstants.ZERO) || (k.compareTo(n) >= 0)) + int nBitLength = n.bitLength(); + BigInteger k; + do { k = new BigInteger(nBitLength, random); } - + while (k.equals(ECConstants.ZERO) || (k.compareTo(n) >= 0)); return k; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java index eb79fc068..895244948 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/encodings/PKCS1Encoding.java @@ -34,6 +34,8 @@ public class PKCS1Encoding private boolean forEncryption; private boolean forPrivateKey; private boolean useStrictLength; + private int pLen = -1; + private byte[] fallback = null; /** * Basic constructor. @@ -46,6 +48,42 @@ public class PKCS1Encoding this.useStrictLength = useStrict(); } + /** + * Constructor for decryption with a fixed plaintext length. + * + * @param cipher The cipher to use for cryptographic operation. + * @param pLen Length of the expected plaintext. + */ + public PKCS1Encoding( + AsymmetricBlockCipher cipher, + int pLen) + { + this.engine = cipher; + this.useStrictLength = useStrict(); + this.pLen = pLen; + } + + /** + * Constructor for decryption with a fixed plaintext length and a fallback + * value that is returned, if the padding is incorrect. + * + * @param cipher + * The cipher to use for cryptographic operation. + * @param fallback + * The fallback value, we don't to a arraycopy here. + */ + public PKCS1Encoding( + AsymmetricBlockCipher cipher, + byte[] fallback) + { + this.engine = cipher; + this.useStrictLength = useStrict(); + this.fallback = fallback; + this.pLen = fallback.length; + } + + + // // for J2ME compatibility // @@ -183,6 +221,121 @@ public class PKCS1Encoding return engine.processBlock(block, 0, block.length); } + + /** + * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext + * for encryption. + * + * @param encoded The Plaintext. + * @param pLen Expected length of the plaintext. + * @return Either 0, if the encoding is correct, or -1, if it is incorrect. + */ + private static int checkPkcs1Encoding(byte[] encoded, int pLen) { + int correct = 0; + /* + * Check if the first two bytes are 0 2 + */ + correct |= (encoded[0] ^ 2); + + /* + * Now the padding check, check for no 0 byte in the padding + */ + int plen = encoded.length - ( + pLen /* Lenght of the PMS */ + + 1 /* Final 0-byte before PMS */ + ); + + for (int i = 1; i < plen; i++) { + int tmp = encoded[i]; + tmp |= tmp >> 1; + tmp |= tmp >> 2; + tmp |= tmp >> 4; + correct |= (tmp & 1) - 1; + } + + /* + * Make sure the padding ends with a 0 byte. + */ + correct |= encoded[encoded.length - (pLen +1)]; + + /* + * Return 0 or 1, depending on the result. + */ + correct |= correct >> 1; + correct |= correct >> 2; + correct |= correct >> 4; + return ~((correct & 1) - 1); + } + + + /** + * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct. + * + * @param in The encrypted block. + * @param inOff Offset in the encrypted block. + * @param inLen Length of the encrypted block. + * //@param pLen Length of the desired output. + * @return The plaintext without padding, or a random value if the padding was incorrect. + * + * @throws InvalidCipherTextException + */ + private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen) + throws InvalidCipherTextException + { + if (!forPrivateKey) + { + throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); + } + + byte[] block = engine.processBlock(in, inOff, inLen); + byte[] random = null; + if (this.fallback == null) + { + random = new byte[this.pLen]; + this.random.nextBytes(random); + } + else + { + random = fallback; + } + + /* + * TODO: This is a potential dangerous side channel. However, you can + * fix this by changing the RSA engine in a way, that it will always + * return blocks of the same length and prepend them with 0 bytes if + * needed. + */ + if (block.length < getOutputBlockSize()) + { + throw new InvalidCipherTextException("block truncated"); + } + + /* + * TODO: Potential side channel. Fix it by making the engine always + * return blocks of the correct length. + */ + if (useStrictLength && block.length != engine.getOutputBlockSize()) + { + throw new InvalidCipherTextException("block incorrect size"); + } + + /* + * Check the padding. + */ + int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen); + + /* + * Now, to a constant time constant memory copy of the decrypted value + * or the random value, depending on the validity of the padding. + */ + byte[] result = new byte[this.pLen]; + for (int i = 0; i < this.pLen; i++) + { + result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct)); + } + + return result; + } /** * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format. @@ -193,7 +346,15 @@ public class PKCS1Encoding int inLen) throws InvalidCipherTextException { - byte[] block = engine.processBlock(in, inOff, inLen); + /* + * If the length of the expected plaintext is known, we use a constant-time decryption. + * If the decryption fails, we return a random value. + */ + if (this.pLen != -1) { + return this.decodeBlockOrRandom(in, inOff, inLen); + } + + byte[] block = engine.processBlock(in, inOff, inLen); if (block.length < getOutputBlockSize()) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java index 9a7dbe84d..bc7e9176c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESEngine.java @@ -473,74 +473,65 @@ private static final int[] Tinv0 = private void encryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; - - C0 ^= KW[0][0]; - C1 ^= KW[0][1]; - C2 ^= KW[0][2]; - C3 ^= KW[0][3]; - - r = 1; + int t0 = this.C0 ^ KW[0][0]; + int t1 = this.C1 ^ KW[0][1]; + int t2 = this.C2 ^ KW[0][2]; + int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3]; while (r < ROUNDS - 1) { - r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255],16) ^ shift(T0[(C3>>24)&255],8) ^ KW[r][0]; - r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1]; - r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2]; - r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3]; - C0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0]; - C1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1]; - C2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2]; - C3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3]; + r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0]; + r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1]; + r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2]; + r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3]; + t0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0]; + t1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1]; + t2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2]; + r3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3]; } - r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255], 16) ^ shift(T0[(C3>>24)&255], 8) ^ KW[r][0]; - r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1]; - r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2]; - r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3]; + r0 = T0[t0&255] ^ shift(T0[(t1>>8)&255], 24) ^ shift(T0[(t2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0]; + r1 = T0[t1&255] ^ shift(T0[(t2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(t0>>24)&255], 8) ^ KW[r][1]; + r2 = T0[t2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(t0>>16)&255], 16) ^ shift(T0[(t1>>24)&255], 8) ^ KW[r][2]; + r3 = T0[r3&255] ^ shift(T0[(t0>>8)&255], 24) ^ shift(T0[(t1>>16)&255], 16) ^ shift(T0[(t2>>24)&255], 8) ^ KW[r++][3]; // the final round's table is a simple function of S so we don't use a whole other four tables for it - C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; - C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; - C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; - C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; - + this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; + this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; + this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; + this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; } private void decryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; + int t0 = this.C0 ^ KW[ROUNDS][0]; + int t1 = this.C1 ^ KW[ROUNDS][1]; + int t2 = this.C2 ^ KW[ROUNDS][2]; - C0 ^= KW[ROUNDS][0]; - C1 ^= KW[ROUNDS][1]; - C2 ^= KW[ROUNDS][2]; - C3 ^= KW[ROUNDS][3]; - - r = ROUNDS-1; - - while (r>1) + int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3]; + while (r > 1) { - r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0]; - r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1]; - r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2]; - r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3]; - C0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0]; - C1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1]; - C2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2]; - C3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3]; + r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0]; + r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1]; + r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2]; + r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r--][3]; + t0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0]; + t1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1]; + t2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2]; + r3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3]; } - r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0]; - r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1]; - r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2]; - r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r][3]; + r0 = Tinv0[t0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(t2>>16)&255], 16) ^ shift(Tinv0[(t1>>24)&255], 8) ^ KW[r][0]; + r1 = Tinv0[t1&255] ^ shift(Tinv0[(t0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(t2>>24)&255], 8) ^ KW[r][1]; + r2 = Tinv0[t2&255] ^ shift(Tinv0[(t1>>8)&255], 24) ^ shift(Tinv0[(t0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2]; + r3 = Tinv0[r3&255] ^ shift(Tinv0[(t2>>8)&255], 24) ^ shift(Tinv0[(t1>>16)&255], 16) ^ shift(Tinv0[(t0>>24)&255], 8) ^ KW[r][3]; // the final round's table is a simple function of Si so we don't use a whole other four tables for it - C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; - C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; - C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; - C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; + this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; + this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; + this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; + this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java index 34f33fd67..4eb705bae 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESFastEngine.java @@ -5,6 +5,7 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.util.Pack; /** * an implementation of the AES (Rijndael), from FIPS-197. @@ -110,8 +111,9 @@ public class AESFastEngine 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 }; // precomputation tables of calculations for rounds - private static final int[] T0 = + private static final int[] T = { + // T0 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, @@ -163,10 +165,9 @@ public class AESFastEngine 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, - 0x3a16162c}; + 0x3a16162c, - private static final int[] T1 = - { + // T1 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, @@ -218,10 +219,9 @@ public class AESFastEngine 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, - 0x16162c3a}; + 0x16162c3a, - private static final int[] T2 = - { + // T2 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, @@ -273,10 +273,9 @@ public class AESFastEngine 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, - 0x162c3a16}; + 0x162c3a16, - private static final int[] T3 = - { + // T3 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, @@ -330,8 +329,9 @@ public class AESFastEngine 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616}; - private static final int[] Tinv0 = + private static final int[] Tinv = { + // Tinv0 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, @@ -383,10 +383,9 @@ public class AESFastEngine 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, - 0x4257b8d0}; + 0x4257b8d0, - private static final int[] Tinv1 = - { + // Tinv1 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, @@ -438,10 +437,9 @@ public class AESFastEngine 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, - 0x57b8d042}; + 0x57b8d042, - private static final int[] Tinv2 = - { + // Tinv2 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, @@ -493,10 +491,9 @@ public class AESFastEngine 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, - 0xb8d04257}; + 0xb8d04257, - private static final int[] Tinv3 = - { + // Tinv3 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, @@ -586,10 +583,11 @@ public class AESFastEngine return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); } - private static int subWord(int x) { - return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24); + int i0 = x, i1 = x >>> 8, i2 = x >>> 16, i3 = x >>> 24; + i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255; + return i0 | i1 << 8 | i2 << 16 | i3 << 24; } /** @@ -727,19 +725,19 @@ public class AESFastEngine throw new OutputLengthException("output buffer too short"); } + unpackBlock(in, inOff); + if (forEncryption) { - unpackBlock(in, inOff); encryptBlock(WorkingKey); - packBlock(out, outOff); } else { - unpackBlock(in, inOff); decryptBlock(WorkingKey); - packBlock(out, outOff); } + packBlock(out, outOff); + return BLOCK_SIZE; } @@ -747,129 +745,184 @@ public class AESFastEngine { } - private void unpackBlock( - byte[] bytes, - int off) + private void unpackBlock(byte[] bytes, int off) { - int index = off; - - C0 = (bytes[index++] & 0xff); - C0 |= (bytes[index++] & 0xff) << 8; - C0 |= (bytes[index++] & 0xff) << 16; - C0 |= bytes[index++] << 24; - - C1 = (bytes[index++] & 0xff); - C1 |= (bytes[index++] & 0xff) << 8; - C1 |= (bytes[index++] & 0xff) << 16; - C1 |= bytes[index++] << 24; - - C2 = (bytes[index++] & 0xff); - C2 |= (bytes[index++] & 0xff) << 8; - C2 |= (bytes[index++] & 0xff) << 16; - C2 |= bytes[index++] << 24; - - C3 = (bytes[index++] & 0xff); - C3 |= (bytes[index++] & 0xff) << 8; - C3 |= (bytes[index++] & 0xff) << 16; - C3 |= bytes[index++] << 24; + this.C0 = Pack.littleEndianToInt(bytes, off); + this.C1 = Pack.littleEndianToInt(bytes, off + 4); + this.C2 = Pack.littleEndianToInt(bytes, off + 8); + this.C3 = Pack.littleEndianToInt(bytes, off + 12); } - private void packBlock( - byte[] bytes, - int off) + private void packBlock(byte[] bytes, int off) { - int index = off; - - bytes[index++] = (byte)C0; - bytes[index++] = (byte)(C0 >> 8); - bytes[index++] = (byte)(C0 >> 16); - bytes[index++] = (byte)(C0 >> 24); - - bytes[index++] = (byte)C1; - bytes[index++] = (byte)(C1 >> 8); - bytes[index++] = (byte)(C1 >> 16); - bytes[index++] = (byte)(C1 >> 24); - - bytes[index++] = (byte)C2; - bytes[index++] = (byte)(C2 >> 8); - bytes[index++] = (byte)(C2 >> 16); - bytes[index++] = (byte)(C2 >> 24); - - bytes[index++] = (byte)C3; - bytes[index++] = (byte)(C3 >> 8); - bytes[index++] = (byte)(C3 >> 16); - bytes[index++] = (byte)(C3 >> 24); + Pack.intToLittleEndian(this.C0, bytes, off); + Pack.intToLittleEndian(this.C1, bytes, off + 4); + Pack.intToLittleEndian(this.C2, bytes, off + 8); + Pack.intToLittleEndian(this.C3, bytes, off + 12); } private void encryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; - - C0 ^= KW[0][0]; - C1 ^= KW[0][1]; - C2 ^= KW[0][2]; - C3 ^= KW[0][3]; + int t0 = this.C0 ^ KW[0][0]; + int t1 = this.C1 ^ KW[0][1]; + int t2 = this.C2 ^ KW[0][2]; + + /* + * Fast engine has precomputed rotr(T0, 8/16/24) tables T1/T2/T3. + * + * Placing all precomputes in one array requires offsets additions for 8/16/24 rotations but + * avoids additional array range checks on 3 more arrays (which on HotSpot are more + * expensive than the offset additions). + */ + int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3]; + int i0, i1, i2, i3; - r = 1; while (r < ROUNDS - 1) { - r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0]; - r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1]; - r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2]; - r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3]; - C0 = T0[r0&255] ^ T1[(r1>>8)&255] ^ T2[(r2>>16)&255] ^ T3[(r3>>24)&255] ^ KW[r][0]; - C1 = T0[r1&255] ^ T1[(r2>>8)&255] ^ T2[(r3>>16)&255] ^ T3[(r0>>24)&255] ^ KW[r][1]; - C2 = T0[r2&255] ^ T1[(r3>>8)&255] ^ T2[(r0>>16)&255] ^ T3[(r1>>24)&255] ^ KW[r][2]; - C3 = T0[r3&255] ^ T1[(r0>>8)&255] ^ T2[(r1>>16)&255] ^ T3[(r2>>24)&255] ^ KW[r++][3]; + i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0]; + + i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1]; + + i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2]; + + i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3]; + + i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0]; + + i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1]; + + i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2]; + + i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3]; } - r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0]; - r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1]; - r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2]; - r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3]; - + i0 = t0; i1 = t1 >>> 8; i2 = t2 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r0 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][0]; + + i0 = t1; i1 = t2 >>> 8; i2 = r3 >>> 16; i3 = t0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r1 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][1]; + + i0 = t2; i1 = r3 >>> 8; i2 = t0 >>> 16; i3 = t1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r2 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r][2]; + + i0 = r3; i1 = t0 >>> 8; i2 = t1 >>> 16; i3 = t2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = T[i0] ^ T[256 + i1] ^ T[512 + i2] ^ T[768 + i3] ^ KW[r++][3]; + // the final round's table is a simple function of S so we don't use a whole other four tables for it - C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; - C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; - C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; - C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; + i0 = r0; i1 = r1 >>> 8; i2 = r2 >>> 16; i3 = r3 >>> 24; + i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255; + this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][0]; + i0 = r1; i1 = r2 >>> 8; i2 = r3 >>> 16; i3 = r0 >>> 24; + i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255; + this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][1]; + + i0 = r2; i1 = r3 >>> 8; i2 = r0 >>> 16; i3 = r1 >>> 24; + i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255; + this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][2]; + + i0 = r3; i1 = r0 >>> 8; i2 = r1 >>> 16; i3 = r2 >>> 24; + i0 = S[i0 & 255] & 255; i1 = S[i1 & 255] & 255; i2 = S[i2 & 255] & 255; i3 = S[i3 & 255] & 255; + this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[r][3]; } private void decryptBlock(int[][] KW) { - int r0, r1, r2, r3; + int t0 = this.C0 ^ KW[ROUNDS][0]; + int t1 = this.C1 ^ KW[ROUNDS][1]; + int t2 = this.C2 ^ KW[ROUNDS][2]; - C0 ^= KW[ROUNDS][0]; - C1 ^= KW[ROUNDS][1]; - C2 ^= KW[ROUNDS][2]; - C3 ^= KW[ROUNDS][3]; + int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3]; + int i0, i1, i2, i3; - int r = ROUNDS-1; - - while (r>1) + while (r > 1) { - r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0]; - r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1]; - r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2]; - r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r--][3]; - C0 = Tinv0[r0&255] ^ Tinv1[(r3>>8)&255] ^ Tinv2[(r2>>16)&255] ^ Tinv3[(r1>>24)&255] ^ KW[r][0]; - C1 = Tinv0[r1&255] ^ Tinv1[(r0>>8)&255] ^ Tinv2[(r3>>16)&255] ^ Tinv3[(r2>>24)&255] ^ KW[r][1]; - C2 = Tinv0[r2&255] ^ Tinv1[(r1>>8)&255] ^ Tinv2[(r0>>16)&255] ^ Tinv3[(r3>>24)&255] ^ KW[r][2]; - C3 = Tinv0[r3&255] ^ Tinv1[(r2>>8)&255] ^ Tinv2[(r1>>16)&255] ^ Tinv3[(r0>>24)&255] ^ KW[r--][3]; + i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0]; + + i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1]; + + i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2]; + + i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3]; + + i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][0]; + + i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][1]; + + i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + t2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r][2]; + + i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[r--][3]; } - r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0]; - r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1]; - r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2]; - r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r][3]; - + i0 = t0; i1 = r3 >>> 8; i2 = t2 >>> 16; i3 = t1 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r0 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][0]; + + i0 = t1; i1 = t0 >>> 8; i2 = r3 >>> 16; i3 = t2 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r1 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][1]; + + i0 = t2; i1 = t1 >>> 8; i2 = t0 >>> 16; i3 = r3 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r2 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][2]; + + i0 = r3; i1 = t2 >>> 8; i2 = t1 >>> 16; i3 = t0 >>> 24; + i0 &= 255; i1 &= 255; i2 &= 255; i3 &= 255; + r3 = Tinv[i0] ^ Tinv[256 + i1] ^ Tinv[512 + i2] ^ Tinv[768 + i3] ^ KW[1][3]; + // the final round's table is a simple function of Si so we don't use a whole other four tables for it - C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; - C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; - C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; - C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; + i0 = r0; i1 = r3 >>> 8; i2 = r2 >>> 16; i3 = r1 >>> 24; + i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255; + this.C0 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][0]; + + i0 = r1; i1 = r0 >>> 8; i2 = r3 >>> 16; i3 = r2 >>> 24; + i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255; + this.C1 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][1]; + + i0 = r2; i1 = r1 >>> 8; i2 = r0 >>> 16; i3 = r3 >>> 24; + i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255; + this.C2 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][2]; + + i0 = r3; i1 = r2 >>> 8; i2 = r1 >>> 16; i3 = r0 >>> 24; + i0 = Si[i0 & 255] & 255; i1 = Si[i1 & 255] & 255; i2 = Si[i2 & 255] & 255; i3 = Si[i3 & 255] & 255; + this.C3 = i0 ^ i1 << 8 ^ i2 << 16 ^ i3 << 24 ^ KW[0][3]; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java index 4baa93a99..07b8e5134 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESLightEngine.java @@ -370,70 +370,65 @@ public class AESLightEngine private void encryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; + int t0 = this.C0 ^ KW[0][0]; + int t1 = this.C1 ^ KW[0][1]; + int t2 = this.C2 ^ KW[0][2]; - C0 ^= KW[0][0]; - C1 ^= KW[0][1]; - C2 ^= KW[0][2]; - C3 ^= KW[0][3]; - - for (r = 1; r < ROUNDS - 1;) + int r = 1, r0, r1, r2, r3 = this.C3 ^ KW[0][3]; + while (r < ROUNDS - 1) { - r0 = mcol((S[C0&255]&255) ^ ((S[(C1>>8)&255]&255)<<8) ^ ((S[(C2>>16)&255]&255)<<16) ^ (S[(C3>>24)&255]<<24)) ^ KW[r][0]; - r1 = mcol((S[C1&255]&255) ^ ((S[(C2>>8)&255]&255)<<8) ^ ((S[(C3>>16)&255]&255)<<16) ^ (S[(C0>>24)&255]<<24)) ^ KW[r][1]; - r2 = mcol((S[C2&255]&255) ^ ((S[(C3>>8)&255]&255)<<8) ^ ((S[(C0>>16)&255]&255)<<16) ^ (S[(C1>>24)&255]<<24)) ^ KW[r][2]; - r3 = mcol((S[C3&255]&255) ^ ((S[(C0>>8)&255]&255)<<8) ^ ((S[(C1>>16)&255]&255)<<16) ^ (S[(C2>>24)&255]<<24)) ^ KW[r++][3]; - C0 = mcol((S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0]; - C1 = mcol((S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24)) ^ KW[r][1]; - C2 = mcol((S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24)) ^ KW[r][2]; - C3 = mcol((S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24)) ^ KW[r++][3]; + r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0]; + r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1]; + r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2]; + r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3]; + t0 = mcol((S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0]; + t1 = mcol((S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24)) ^ KW[r][1]; + t2 = mcol((S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24)) ^ KW[r][2]; + r3 = mcol((S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24)) ^ KW[r++][3]; } - r0 = mcol((S[C0&255]&255) ^ ((S[(C1>>8)&255]&255)<<8) ^ ((S[(C2>>16)&255]&255)<<16) ^ (S[(C3>>24)&255]<<24)) ^ KW[r][0]; - r1 = mcol((S[C1&255]&255) ^ ((S[(C2>>8)&255]&255)<<8) ^ ((S[(C3>>16)&255]&255)<<16) ^ (S[(C0>>24)&255]<<24)) ^ KW[r][1]; - r2 = mcol((S[C2&255]&255) ^ ((S[(C3>>8)&255]&255)<<8) ^ ((S[(C0>>16)&255]&255)<<16) ^ (S[(C1>>24)&255]<<24)) ^ KW[r][2]; - r3 = mcol((S[C3&255]&255) ^ ((S[(C0>>8)&255]&255)<<8) ^ ((S[(C1>>16)&255]&255)<<16) ^ (S[(C2>>24)&255]<<24)) ^ KW[r++][3]; + r0 = mcol((S[t0&255]&255) ^ ((S[(t1>>8)&255]&255)<<8) ^ ((S[(t2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0]; + r1 = mcol((S[t1&255]&255) ^ ((S[(t2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(t0>>24)&255]<<24)) ^ KW[r][1]; + r2 = mcol((S[t2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(t0>>16)&255]&255)<<16) ^ (S[(t1>>24)&255]<<24)) ^ KW[r][2]; + r3 = mcol((S[r3&255]&255) ^ ((S[(t0>>8)&255]&255)<<8) ^ ((S[(t1>>16)&255]&255)<<16) ^ (S[(t2>>24)&255]<<24)) ^ KW[r++][3]; // the final round is a simple function of S - C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; - C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; - C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; - C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; - + this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; + this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; + this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; + this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; } private void decryptBlock(int[][] KW) { - int r, r0, r1, r2, r3; + int t0 = this.C0 ^ KW[ROUNDS][0]; + int t1 = this.C1 ^ KW[ROUNDS][1]; + int t2 = this.C2 ^ KW[ROUNDS][2]; - C0 ^= KW[ROUNDS][0]; - C1 ^= KW[ROUNDS][1]; - C2 ^= KW[ROUNDS][2]; - C3 ^= KW[ROUNDS][3]; - - for (r = ROUNDS-1; r>1;) + int r = ROUNDS - 1, r0, r1, r2, r3 = this.C3 ^ KW[ROUNDS][3]; + while (r > 1) { - r0 = inv_mcol((Si[C0&255]&255) ^ ((Si[(C3>>8)&255]&255)<<8) ^ ((Si[(C2>>16)&255]&255)<<16) ^ (Si[(C1>>24)&255]<<24)) ^ KW[r][0]; - r1 = inv_mcol((Si[C1&255]&255) ^ ((Si[(C0>>8)&255]&255)<<8) ^ ((Si[(C3>>16)&255]&255)<<16) ^ (Si[(C2>>24)&255]<<24)) ^ KW[r][1]; - r2 = inv_mcol((Si[C2&255]&255) ^ ((Si[(C1>>8)&255]&255)<<8) ^ ((Si[(C0>>16)&255]&255)<<16) ^ (Si[(C3>>24)&255]<<24)) ^ KW[r][2]; - r3 = inv_mcol((Si[C3&255]&255) ^ ((Si[(C2>>8)&255]&255)<<8) ^ ((Si[(C1>>16)&255]&255)<<16) ^ (Si[(C0>>24)&255]<<24)) ^ KW[r--][3]; - C0 = inv_mcol((Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24)) ^ KW[r][0]; - C1 = inv_mcol((Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24)) ^ KW[r][1]; - C2 = inv_mcol((Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2]; - C3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24)) ^ KW[r--][3]; + r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0]; + r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1]; + r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2]; + r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r--][3]; + t0 = inv_mcol((Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24)) ^ KW[r][0]; + t1 = inv_mcol((Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24)) ^ KW[r][1]; + t2 = inv_mcol((Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2]; + r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24)) ^ KW[r--][3]; } - r0 = inv_mcol((Si[C0&255]&255) ^ ((Si[(C3>>8)&255]&255)<<8) ^ ((Si[(C2>>16)&255]&255)<<16) ^ (Si[(C1>>24)&255]<<24)) ^ KW[r][0]; - r1 = inv_mcol((Si[C1&255]&255) ^ ((Si[(C0>>8)&255]&255)<<8) ^ ((Si[(C3>>16)&255]&255)<<16) ^ (Si[(C2>>24)&255]<<24)) ^ KW[r][1]; - r2 = inv_mcol((Si[C2&255]&255) ^ ((Si[(C1>>8)&255]&255)<<8) ^ ((Si[(C0>>16)&255]&255)<<16) ^ (Si[(C3>>24)&255]<<24)) ^ KW[r][2]; - r3 = inv_mcol((Si[C3&255]&255) ^ ((Si[(C2>>8)&255]&255)<<8) ^ ((Si[(C1>>16)&255]&255)<<16) ^ (Si[(C0>>24)&255]<<24)) ^ KW[r][3]; + r0 = inv_mcol((Si[t0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(t2>>16)&255]&255)<<16) ^ (Si[(t1>>24)&255]<<24)) ^ KW[r][0]; + r1 = inv_mcol((Si[t1&255]&255) ^ ((Si[(t0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(t2>>24)&255]<<24)) ^ KW[r][1]; + r2 = inv_mcol((Si[t2&255]&255) ^ ((Si[(t1>>8)&255]&255)<<8) ^ ((Si[(t0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2]; + r3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(t2>>8)&255]&255)<<8) ^ ((Si[(t1>>16)&255]&255)<<16) ^ (Si[(t0>>24)&255]<<24)) ^ KW[r][3]; // the final round's table is a simple function of Si - C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; - C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; - C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; - C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; + this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; + this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; + this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; + this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java new file mode 100644 index 000000000..03170ec65 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/AESWrapPadEngine.java @@ -0,0 +1,10 @@ +package org.spongycastle.crypto.engines; + +public class AESWrapPadEngine + extends RFC5649WrapEngine +{ + public AESWrapPadEngine() + { + super(new AESEngine()); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java index a6a0138b9..bcceed9c8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ChaChaEngine.java @@ -1,13 +1,12 @@ package org.spongycastle.crypto.engines; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * Implementation of Daniel J. Bernstein's ChaCha stream cipher. */ public class ChaChaEngine extends Salsa20Engine { - /** * Creates a 20 rounds ChaCha engine. */ @@ -38,6 +37,24 @@ public class ChaChaEngine extends Salsa20Engine } } + protected void retreatCounter() + { + if (engineState[12] == 0 && engineState[13] == 0) + { + throw new IllegalStateException("attempt to reduce counter past zero."); + } + + if (--engineState[12] == -1) + { + --engineState[13]; + } + } + + protected long getCounter() + { + return ((long)engineState[13] << 32) | (engineState[12] & 0xffffffffL); + } + protected void resetCounter() { engineState[12] = engineState[13] = 0; @@ -45,42 +62,43 @@ public class ChaChaEngine extends Salsa20Engine protected void setKey(byte[] keyBytes, byte[] ivBytes) { - if ((keyBytes.length != 16) && (keyBytes.length != 32)) + if (keyBytes != null) { - throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key"); + if ((keyBytes.length != 16) && (keyBytes.length != 32)) + { + throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key"); + } + + // Key + engineState[4] = Pack.littleEndianToInt(keyBytes, 0); + engineState[5] = Pack.littleEndianToInt(keyBytes, 4); + engineState[6] = Pack.littleEndianToInt(keyBytes, 8); + engineState[7] = Pack.littleEndianToInt(keyBytes, 12); + + byte[] constants; + int offset; + if (keyBytes.length == 32) + { + constants = sigma; + offset = 16; + } + else + { + constants = tau; + offset = 0; + } + + engineState[8] = Pack.littleEndianToInt(keyBytes, offset); + engineState[9] = Pack.littleEndianToInt(keyBytes, offset + 4); + engineState[10] = Pack.littleEndianToInt(keyBytes, offset + 8); + engineState[11] = Pack.littleEndianToInt(keyBytes, offset + 12); + + engineState[0] = Pack.littleEndianToInt(constants, 0); + engineState[1] = Pack.littleEndianToInt(constants, 4); + engineState[2] = Pack.littleEndianToInt(constants, 8); + engineState[3] = Pack.littleEndianToInt(constants, 12); } - int offset = 0; - byte[] constants; - - // Key - engineState[4] = Pack.littleEndianToInt(keyBytes, 0); - engineState[5] = Pack.littleEndianToInt(keyBytes, 4); - engineState[6] = Pack.littleEndianToInt(keyBytes, 8); - engineState[7] = Pack.littleEndianToInt(keyBytes, 12); - - if (keyBytes.length == 32) - { - constants = sigma; - offset = 16; - } else - { - constants = tau; - } - - engineState[8] = Pack.littleEndianToInt(keyBytes, offset); - engineState[9] = Pack.littleEndianToInt(keyBytes, offset + 4); - engineState[10] = Pack.littleEndianToInt(keyBytes, offset + 8); - engineState[11] = Pack.littleEndianToInt(keyBytes, offset + 12); - - engineState[0] = Pack.littleEndianToInt(constants, 0); - engineState[1] = Pack.littleEndianToInt(constants, 4); - engineState[2] = Pack.littleEndianToInt(constants, 8); - engineState[3] = Pack.littleEndianToInt(constants, 12); - - // Counter - engineState[12] = engineState[13] = 0; - // IV engineState[14] = Pack.littleEndianToInt(ivBytes, 0); engineState[15] = Pack.littleEndianToInt(ivBytes, 4); @@ -96,18 +114,19 @@ public class ChaChaEngine extends Salsa20Engine * ChacCha function * * @param input input data - * - * @return keystream */ public static void chachaCore(int rounds, int[] input, int[] x) { - if (input.length != 16) { + if (input.length != 16) + { throw new IllegalArgumentException(); } - if (x.length != 16) { + if (x.length != 16) + { throw new IllegalArgumentException(); } - if (rounds % 2 != 0) { + if (rounds % 2 != 0) + { throw new IllegalArgumentException("Number of rounds must be even"); } @@ -182,5 +201,4 @@ public class ChaChaEngine extends Salsa20Engine x[14] = x14 + input[14]; x[15] = x15 + input[15]; } - } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java new file mode 100644 index 000000000..c5d61aac8 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCiphertext.java @@ -0,0 +1,179 @@ +package org.spongycastle.crypto.engines; + +import java.math.BigInteger; + +/** + * Class, holding Cramer Shoup ciphertexts (u1, u2, e, v) + */ +public class CramerShoupCiphertext +{ + + BigInteger u1, u2, e, v; + + public CramerShoupCiphertext() + { + + } + + public CramerShoupCiphertext(BigInteger u1, BigInteger u2, BigInteger e, BigInteger v) + { + this.u1 = u1; + this.u2 = u2; + this.e = e; + this.v = v; + } + + public CramerShoupCiphertext(byte[] c) + { + int off = 0, s; + byte[] size = new byte[4]; + byte[] tmp; + + System.arraycopy(c, off, size, 0, 4); + s = byteArrayToInt(size); + tmp = new byte[s]; + off += 4; + System.arraycopy(c, off, tmp, 0, s); + off += s; + u1 = new BigInteger(tmp); + + System.arraycopy(c, off, size, 0, 4); + s = byteArrayToInt(size); + tmp = new byte[s]; + off += 4; + System.arraycopy(c, off, tmp, 0, s); + off += s; + u2 = new BigInteger(tmp); + + System.arraycopy(c, off, size, 0, 4); + s = byteArrayToInt(size); + tmp = new byte[s]; + off += 4; + System.arraycopy(c, off, tmp, 0, s); + off += s; + e = new BigInteger(tmp); + + System.arraycopy(c, off, size, 0, 4); + s = byteArrayToInt(size); + tmp = new byte[s]; + off += 4; + System.arraycopy(c, off, tmp, 0, s); + off += s; + v = new BigInteger(tmp); + } + + public BigInteger getU1() + { + return u1; + } + + public void setU1(BigInteger u1) + { + this.u1 = u1; + } + + public BigInteger getU2() + { + return u2; + } + + public void setU2(BigInteger u2) + { + this.u2 = u2; + } + + public BigInteger getE() + { + return e; + } + + public void setE(BigInteger e) + { + this.e = e; + } + + public BigInteger getV() + { + return v; + } + + public void setV(BigInteger v) + { + this.v = v; + } + + public String toString() + { + StringBuffer result = new StringBuffer(); + + result.append("u1: " + u1.toString()); + result.append("\nu2: " + u2.toString()); + result.append("\ne: " + e.toString()); + result.append("\nv: " + v.toString()); + + return result.toString(); + } + + /** + * convert the cipher-text in a byte array, + * prepending them with 4 Bytes for their length + * + * @return + */ + public byte[] toByteArray() + { + + byte[] u1Bytes = u1.toByteArray(); + int u1Length = u1Bytes.length; + byte[] u2Bytes = u2.toByteArray(); + int u2Length = u2Bytes.length; + byte[] eBytes = e.toByteArray(); + int eLength = eBytes.length; + byte[] vBytes = v.toByteArray(); + int vLength = vBytes.length; + + int off = 0; + byte[] result = new byte[u1Length + u2Length + eLength + vLength + 4 * 4]; + System.arraycopy(intToByteArray(u1Length), 0, result, 0, 4); + off += 4; + System.arraycopy(u1Bytes, 0, result, off, u1Length); + off += u1Length; + System.arraycopy(intToByteArray(u2Length), 0, result, off, 4); + off += 4; + System.arraycopy(u2Bytes, 0, result, off, u2Length); + off += u2Length; + System.arraycopy(intToByteArray(eLength), 0, result, off, 4); + off += 4; + System.arraycopy(eBytes, 0, result, off, eLength); + off += eLength; + System.arraycopy(intToByteArray(vLength), 0, result, off, 4); + off += 4; + System.arraycopy(vBytes, 0, result, off, vLength); + + return result; + } + + private byte[] intToByteArray(int in) + { + byte[] bytes = new byte[4]; + for (int i = 0; i < 4; i++) + { + bytes[3 - i] = (byte)(in >>> (i * 8)); + } + return bytes; + } + + private int byteArrayToInt(byte[] in) + { + if (in.length != 4) + { + return -1; + } + int r = 0; + for (int i = 3; i >= 0; i--) + { + r += (int)in[i] << ((3 - i) * 8); + } + return r; + } +} \ No newline at end of file diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java new file mode 100644 index 000000000..894b13d8b --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/CramerShoupCoreEngine.java @@ -0,0 +1,313 @@ +package org.spongycastle.crypto.engines; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.params.CramerShoupKeyParameters; +import org.spongycastle.crypto.params.CramerShoupPrivateKeyParameters; +import org.spongycastle.crypto.params.CramerShoupPublicKeyParameters; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.util.BigIntegers; + +/** + * Essentially the Cramer-Shoup encryption / decryption algorithms according to + * "A practical public key cryptosystem provably secure against adaptive chosen ciphertext attack." (Crypto 1998) + */ +public class CramerShoupCoreEngine +{ + + private static final BigInteger ONE = BigInteger.valueOf(1); + + private CramerShoupKeyParameters key; + private SecureRandom random; + private boolean forEncryption; + private String label = null; + + /** + * initialise the CramerShoup engine. + * + * @param forEncryption whether this engine should encrypt or decrypt + * @param param the necessary CramerShoup key parameters. + * @param label the label for labelled CS as {@link String} + */ + public void init(boolean forEncryption, CipherParameters param, String label) + { + init(forEncryption, param); + + this.label = label; + } + + /** + * initialise the CramerShoup engine. + * + * @param forEncryption whether this engine should encrypt or decrypt + * @param param the necessary CramerShoup key parameters. + */ + public void init(boolean forEncryption, CipherParameters param) + { + SecureRandom providedRandom = null; + + if (param instanceof ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + key = (CramerShoupKeyParameters)rParam.getParameters(); + providedRandom = rParam.getRandom(); + } + else + { + key = (CramerShoupKeyParameters)param; + } + + this.random = initSecureRandom(forEncryption, providedRandom); + this.forEncryption = forEncryption; + } + + /** + * Return the maximum size for an input block to this engine. For Cramer + * Shoup this is always one byte less than the key size on encryption, and + * the same length as the key size on decryption. + * + * @return maximum size for an input block. + * + * TODO: correct? + */ + public int getInputBlockSize() + { + int bitSize = key.getParameters().getP().bitLength(); + + if (forEncryption) + { + return (bitSize + 7) / 8 - 1; + } + else + { + return (bitSize + 7) / 8; + } + } + + /** + * Return the maximum size for an output block to this engine. For Cramer + * Shoup this is always one byte less than the key size on decryption, and + * the same length as the key size on encryption. + * + * @return maximum size for an output block. + * + * TODO: correct? + */ + public int getOutputBlockSize() + { + int bitSize = key.getParameters().getP().bitLength(); + + if (forEncryption) + { + return (bitSize + 7) / 8; + } + else + { + return (bitSize + 7) / 8 - 1; + } + } + + public BigInteger convertInput(byte[] in, int inOff, int inLen) + { + if (inLen > (getInputBlockSize() + 1)) + { + throw new DataLengthException("input too large for Cramer Shoup cipher."); + } + else if (inLen == (getInputBlockSize() + 1) && forEncryption) + { + throw new DataLengthException("input too large for Cramer Shoup cipher."); + } + + byte[] block; + + if (inOff != 0 || inLen != in.length) + { + block = new byte[inLen]; + + System.arraycopy(in, inOff, block, 0, inLen); + } + else + { + block = in; + } + + BigInteger res = new BigInteger(1, block); + if (res.compareTo(key.getParameters().getP()) >= 0) + { + throw new DataLengthException("input too large for Cramer Shoup cipher."); + } + + return res; + } + + public byte[] convertOutput(BigInteger result) + { + byte[] output = result.toByteArray(); + + if (!forEncryption) + { + if (output[0] == 0 && output.length > getOutputBlockSize()) + { // have ended up with an extra zero byte, copy down. + byte[] tmp = new byte[output.length - 1]; + + System.arraycopy(output, 1, tmp, 0, tmp.length); + + return tmp; + } + + if (output.length < getOutputBlockSize()) + {// have ended up with less bytes than normal, lengthen + byte[] tmp = new byte[getOutputBlockSize()]; + + System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length); + + return tmp; + } + } + else + { + if (output[0] == 0) + { // have ended up with an extra zero byte, copy down. + byte[] tmp = new byte[output.length - 1]; + + System.arraycopy(output, 1, tmp, 0, tmp.length); + + return tmp; + } + } + + return output; + } + + public CramerShoupCiphertext encryptBlock(BigInteger input) + { + + CramerShoupCiphertext result = null; + + if (!key.isPrivate() && this.forEncryption && key instanceof CramerShoupPublicKeyParameters) + { + CramerShoupPublicKeyParameters pk = (CramerShoupPublicKeyParameters)key; + BigInteger p = pk.getParameters().getP(); + BigInteger g1 = pk.getParameters().getG1(); + BigInteger g2 = pk.getParameters().getG2(); + + BigInteger h = pk.getH(); + + if (!isValidMessage(input, p)) + { + return result; + } + + BigInteger r = generateRandomElement(p, random); + + BigInteger u1, u2, v, e, a; + + u1 = g1.modPow(r, p); + u2 = g2.modPow(r, p); + e = h.modPow(r, p).multiply(input).mod(p); + + Digest digest = pk.getParameters().getH(); + byte[] u1Bytes = u1.toByteArray(); + digest.update(u1Bytes, 0, u1Bytes.length); + byte[] u2Bytes = u2.toByteArray(); + digest.update(u2Bytes, 0, u2Bytes.length); + byte[] eBytes = e.toByteArray(); + digest.update(eBytes, 0, eBytes.length); + if (this.label != null) + { + byte[] lBytes = this.label.getBytes(); + digest.update(lBytes, 0, lBytes.length); + } + byte[] out = new byte[digest.getDigestSize()]; + digest.doFinal(out, 0); + a = new BigInteger(1, out); + + v = pk.getC().modPow(r, p).multiply(pk.getD().modPow(r.multiply(a), p)).mod(p); + + result = new CramerShoupCiphertext(u1, u2, e, v); + } + return result; + } + + public BigInteger decryptBlock(CramerShoupCiphertext input) + throws CramerShoupCiphertextException + { + + BigInteger result = null; + + if (key.isPrivate() && !this.forEncryption && key instanceof CramerShoupPrivateKeyParameters) + { + CramerShoupPrivateKeyParameters sk = (CramerShoupPrivateKeyParameters)key; + + BigInteger p = sk.getParameters().getP(); + + Digest digest = sk.getParameters().getH(); + byte[] u1Bytes = input.getU1().toByteArray(); + digest.update(u1Bytes, 0, u1Bytes.length); + byte[] u2Bytes = input.getU2().toByteArray(); + digest.update(u2Bytes, 0, u2Bytes.length); + byte[] eBytes = input.getE().toByteArray(); + digest.update(eBytes, 0, eBytes.length); + if (this.label != null) + { + byte[] lBytes = this.label.getBytes(); + digest.update(lBytes, 0, lBytes.length); + } + byte[] out = new byte[digest.getDigestSize()]; + digest.doFinal(out, 0); + + BigInteger a = new BigInteger(1, out); + BigInteger v = input.u1.modPow(sk.getX1().add(sk.getY1().multiply(a)), p). + multiply(input.u2.modPow(sk.getX2().add(sk.getY2().multiply(a)), p)).mod(p); + + // check correctness of ciphertext + if (input.v.equals(v)) + { + result = input.e.multiply(input.u1.modPow(sk.getZ(), p).modInverse(p)).mod(p); + } + else + { + throw new CramerShoupCiphertextException("Sorry, that ciphertext is not correct"); + } + } + return result; + } + + private BigInteger generateRandomElement(BigInteger p, SecureRandom random) + { + return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random); + } + + /** + * just checking whether the message m is actually less than the group order p + */ + private boolean isValidMessage(BigInteger m, BigInteger p) + { + return m.compareTo(p) < 0; + } + + protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided) + { + return !needed ? null : (provided != null) ? provided : new SecureRandom(); + } + + /** + * CS exception for wrong cipher-texts + */ + public static class CramerShoupCiphertextException + extends Exception + { + private static final long serialVersionUID = -6360977166495345076L; + + public CramerShoupCiphertextException(String msg) + { + super(msg); + } + + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java index 68d7ea156..8f43249a8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESEngine.java @@ -301,7 +301,7 @@ public class DESEngine * generate an integer based working key based on our secret key * and what we processing we are planning to do. * - * Acknowledgements for this routine go to James Gillogly & Phil Karn. + * Acknowledgements for this routine go to James Gillogly & Phil Karn. * (whoever, and wherever they are!). */ protected int[] generateWorkingKey( diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java index e03c8cb36..756fe7059 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/DESedeWrapEngine.java @@ -58,8 +58,8 @@ public class DESedeWrapEngine /** * Method init * - * @param forWrapping - * @param param + * @param forWrapping true if for wrapping, false otherwise. + * @param param necessary parameters, may include KeyParameter, ParametersWithRandom, and ParametersWithIV */ public void init(boolean forWrapping, CipherParameters param) { @@ -128,9 +128,9 @@ public class DESedeWrapEngine /** * Method wrap * - * @param in - * @param inOff - * @param inLen + * @param in byte array containing the encoded key. + * @param inOff off set into in that the data starts at. + * @param inLen length of the data. * @return the wrapped bytes. */ public byte[] wrap(byte[] in, int inOff, int inLen) @@ -199,9 +199,9 @@ public class DESedeWrapEngine /** * Method unwrap * - * @param in - * @param inOff - * @param inLen + * @param in byte array containing the wrapped key. + * @param inOff off set into in that the data starts at. + * @param inLen length of the data. * @return the unwrapped bytes. * @throws InvalidCipherTextException */ @@ -305,10 +305,11 @@ public class DESedeWrapEngine * - Compute the 20 octet SHA-1 hash on the key being wrapped. * - Use the first 8 octets of this hash as the checksum value. * - * @param key + * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum. + * + * @param key the key to check, * @return the CMS checksum. * @throws RuntimeException - * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ private byte[] calculateCMSKeyChecksum( byte[] key) @@ -324,10 +325,11 @@ public class DESedeWrapEngine } /** - * @param key - * @param checksum + * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + * + * @param key key to be validated. + * @param checksum the checksum. * @return true if okay, false otherwise. - * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ private boolean checkCMSKeyChecksum( byte[] key, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java index 3a2939bad..cf4799b0c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ElGamalEngine.java @@ -1,5 +1,8 @@ package org.spongycastle.crypto.engines; +import java.math.BigInteger; +import java.security.SecureRandom; + import org.spongycastle.crypto.AsymmetricBlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; @@ -9,9 +12,6 @@ import org.spongycastle.crypto.params.ElGamalPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.util.BigIntegers; -import java.math.BigInteger; -import java.security.SecureRandom; - /** * this does your basic ElGamal algorithm. */ @@ -170,7 +170,7 @@ public class ElGamalEngine BigInteger input = new BigInteger(1, block); - if (input.bitLength() >= p.bitLength()) + if (input.compareTo(p) >= 0) { throw new DataLengthException("input too large for ElGamal cipher.\n"); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java index c96ba5b91..eedd26c73 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grain128Engine.java @@ -232,7 +232,7 @@ public class Grain128Engine } } - public void processBytes(byte[] in, int inOff, int len, byte[] out, + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { @@ -256,6 +256,8 @@ public class Grain128Engine { out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream()); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java index cd034bee1..69f787722 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Grainv1Engine.java @@ -220,7 +220,7 @@ public class Grainv1Engine } } - public void processBytes(byte[] in, int inOff, int len, byte[] out, + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { @@ -244,6 +244,8 @@ public class Grainv1Engine { out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream()); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java index bd935e601..93882825f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC128Engine.java @@ -220,7 +220,7 @@ public class HC128Engine return ret; } - public void processBytes(byte[] in, int inOff, int len, byte[] out, + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { if (!initialised) @@ -243,6 +243,8 @@ public class HC128Engine { out[outOff + i] = (byte)(in[inOff + i] ^ getByte()); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java index 2c2a45a0d..4e42672b2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/HC256Engine.java @@ -200,7 +200,7 @@ public class HC256Engine return ret; } - public void processBytes(byte[] in, int inOff, int len, byte[] out, + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { if (!initialised) @@ -223,6 +223,8 @@ public class HC256Engine { out[outOff + i] = (byte)(in[inOff + i] ^ getByte()); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java index 11f9ef19c..68cef879b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IDEAEngine.java @@ -10,22 +10,12 @@ import org.spongycastle.crypto.params.KeyParameter; * A class that provides a basic International Data Encryption Algorithm (IDEA) engine. ** This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM" - * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (baring 1 typo at the + * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (barring 1 typo at the * end of the mulinv function!). *
* It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/ *
- * Note 1: This algorithm is patented in the USA, Japan, and Europe including - * at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland - * and the United Kingdom. Non-commercial use is free, however any commercial - * products are liable for royalties. Please see - * www.mediacrypt.com for - * further details. This announcement has been included at the request of - * the patent holders. - *
- * Note 2: Due to the requests concerning the above, this algorithm is now only - * included in the extended Bouncy Castle provider and JCE signed jars. It is - * not included in the default distributions. + * Note: This algorithm was patented in the USA, Japan and Europe. These patents expired in 2011/2012. */ public class IDEAEngine implements BlockCipher diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java index 892f25c74..1aebdf4db 100755 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/IESEngine.java @@ -18,9 +18,10 @@ import org.spongycastle.crypto.params.IESParameters; import org.spongycastle.crypto.params.IESWithCipherParameters; import org.spongycastle.crypto.params.KDFParameters; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; +import org.spongycastle.util.Pack; /** * Support class for constructing integrated encryption ciphers @@ -42,7 +43,7 @@ public class IESEngine byte[] V; private EphemeralKeyPairGenerator keyPairGenerator; private KeyParser keyParser; - + private byte[] IV; /** * set up for use with stream mode, where the key derivation function @@ -87,26 +88,26 @@ public class IESEngine 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. + * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher. */ public void init( boolean forEncryption, CipherParameters privParam, CipherParameters pubParam, - CipherParameters param) + CipherParameters params) { this.forEncryption = forEncryption; this.privParam = privParam; this.pubParam = pubParam; - this.param = (IESParameters)param; this.V = new byte[0]; + + extractParams(params); } @@ -114,30 +115,46 @@ public class IESEngine * Initialise the encryptor. * * @param publicKey the recipient's/sender's public key parameters - * @param params encoding and derivation parameters. + * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher. * @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; + + extractParams(params); } /** * Initialise the encryptor. * * @param privateKey the recipient's private key. - * @param params encoding and derivation parameters. + * @param params encoding and derivation parameters, may be wrapped to include an IV for an underlying block cipher. * @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; + + extractParams(params); + } + + private void extractParams(CipherParameters params) + { + if (params instanceof ParametersWithIV) + { + this.IV = ((ParametersWithIV)params).getIV(); + this.param = (IESParameters)((ParametersWithIV)params).getParameters(); + } + else + { + this.IV = null; + this.param = (IESParameters)params; + } } public BufferedBlockCipher getCipher() @@ -198,7 +215,16 @@ public class IESEngine System.arraycopy(K, 0, K1, 0, K1.length); System.arraycopy(K, K1.length, K2, 0, K2.length); - cipher.init(true, new KeyParameter(K1)); + // If iv provided use it to initialise the cipher + if (IV != null) + { + cipher.init(true, new ParametersWithIV(new KeyParameter(K1), IV)); + } + else + { + 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); @@ -247,6 +273,12 @@ public class IESEngine byte[] M = null, K = null, K1 = null, K2 = null; int len; + // Ensure that the length of the input is greater than the MAC in bytes + if (inLen <= (param.getMacKeySize() / 8)) + { + throw new InvalidCipherTextException("Length of input must be greater than the MAC"); + } + if (cipher == null) { // Streaming mode. @@ -287,7 +319,15 @@ public class IESEngine System.arraycopy(K, 0, K1, 0, K1.length); System.arraycopy(K, K1.length, K2, 0, K2.length); - cipher.init(false, new KeyParameter(K1)); + // If IV provide use it to initialize the cipher + if (IV != null) + { + cipher.init(false, new ParametersWithIV(new KeyParameter(K1), IV)); + } + else + { + 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); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java index 5c15db1d1..36e762da6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ISAACEngine.java @@ -5,7 +5,7 @@ import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count). @@ -69,7 +69,7 @@ public class ISAACEngine return out; } - public void processBytes( + public int processBytes( byte[] in, int inOff, int len, @@ -101,6 +101,8 @@ public class ISAACEngine out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]); index = (index + 1) & 1023; } + + return len; } public String getAlgorithmName() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java index 000d0228d..4203954e6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC2WrapEngine.java @@ -350,10 +350,11 @@ public class RC2WrapEngine * - Compute the 20 octet SHA-1 hash on the key being wrapped. * - Use the first 8 octets of this hash as the checksum value. * + * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum * @param key * @return * @throws RuntimeException - * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + * */ private byte[] calculateCMSKeyChecksum( byte[] key) @@ -369,10 +370,11 @@ public class RC2WrapEngine } /** + * For details see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum + * * @param key * @param checksum * @return - * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ private boolean checkCMSKeyChecksum( byte[] key, diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java index 712426f1e..e7ff73a95 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RC4Engine.java @@ -68,7 +68,7 @@ public class RC4Engine implements StreamCipher return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } - public void processBytes( + public int processBytes( byte[] in, int inOff, int len, @@ -99,6 +99,8 @@ public class RC4Engine implements StreamCipher out[i+outOff] = (byte)(in[i + inOff] ^ engineState[(engineState[x] + engineState[y]) & 0xff]); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java new file mode 100644 index 000000000..59cd77326 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/RFC5649WrapEngine.java @@ -0,0 +1,294 @@ +package org.spongycastle.crypto.engines; + +import org.spongycastle.crypto.BlockCipher; +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.Wrapper; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; + +/** + * An implementation of the AES Key Wrap with Padding specification + * as described in RFC 5649. + *
+ * For details on the specification see: + * https://tools.ietf.org/html/rfc5649 + *
+ */ +public class RFC5649WrapEngine + implements Wrapper +{ + private BlockCipher engine; + private KeyParameter param; + private boolean forWrapping; + + // The AIV as defined in the RFC + private byte[] highOrderIV = {(byte)0xa6, (byte)0x59, (byte)0x59, (byte)0xa6}; + private byte[] preIV = highOrderIV; + + private byte[] extractedAIV = null; + + public RFC5649WrapEngine(BlockCipher engine) + { + this.engine = engine; + } + + public void init(boolean forWrapping, CipherParameters param) + { + this.forWrapping = forWrapping; + + if (param instanceof ParametersWithRandom) + { + param = ((ParametersWithRandom)param).getParameters(); + } + + if (param instanceof KeyParameter) + { + this.param = (KeyParameter)param; + } + else if (param instanceof ParametersWithIV) + { + this.preIV = ((ParametersWithIV)param).getIV(); + this.param = (KeyParameter)((ParametersWithIV)param).getParameters(); + if (this.preIV.length != 4) + { + throw new IllegalArgumentException("IV length not equal to 4"); + } + } + } + + public String getAlgorithmName() + { + return engine.getAlgorithmName(); + } + + /** + * Pads the plaintext (i.e., the key to be wrapped) + * as per section 4.1 of RFC 5649. + * + * @param plaintext The key being wrapped. + * @return The padded key. + */ + private byte[] padPlaintext(byte[] plaintext) + { + int plaintextLength = plaintext.length; + int numOfZerosToAppend = (8 - (plaintextLength % 8)) % 8; + byte[] paddedPlaintext = new byte[plaintextLength + numOfZerosToAppend]; + System.arraycopy(plaintext, 0, paddedPlaintext, 0, plaintextLength); + if (numOfZerosToAppend != 0) + { + // plaintext (i.e., key to be wrapped) does not have + // a multiple of 8 octet blocks so it must be padded + byte[] zeros = new byte[numOfZerosToAppend]; + System.arraycopy(zeros, 0, paddedPlaintext, plaintextLength, numOfZerosToAppend); + } + return paddedPlaintext; + } + + public byte[] wrap(byte[] in, int inOff, int inLen) + { + if (!forWrapping) + { + throw new IllegalStateException("not set for wrapping"); + } + byte[] iv = new byte[8]; + + // MLI = size of key to be wrapped + byte[] mli = Pack.intToBigEndian(inLen); + // copy in the fixed portion of the AIV + System.arraycopy(preIV, 0, iv, 0, preIV.length); + // copy in the MLI after the AIV + System.arraycopy(mli, 0, iv, preIV.length, mli.length); + + // get the relevant plaintext to be wrapped + byte[] relevantPlaintext = new byte[inLen]; + System.arraycopy(in, inOff, relevantPlaintext, 0, inLen); + byte[] paddedPlaintext = padPlaintext(relevantPlaintext); + + if (paddedPlaintext.length == 8) + { + // if the padded plaintext contains exactly 8 octets, + // then prepend iv and encrypt using AES in ECB mode. + + // prepend the IV to the plaintext + byte[] paddedPlainTextWithIV = new byte[paddedPlaintext.length + iv.length]; + System.arraycopy(iv, 0, paddedPlainTextWithIV, 0, iv.length); + System.arraycopy(paddedPlaintext, 0, paddedPlainTextWithIV, iv.length, paddedPlaintext.length); + + engine.init(true, param); + for (int i = 0; i < paddedPlainTextWithIV.length; i += engine.getBlockSize()) + { + engine.processBlock(paddedPlainTextWithIV, i, paddedPlainTextWithIV, i); + } + + return paddedPlainTextWithIV; + } + else + { + // otherwise, apply the RFC 3394 wrap to + // the padded plaintext with the new IV + Wrapper wrapper = new RFC3394WrapEngine(engine); + ParametersWithIV paramsWithIV = new ParametersWithIV(param, iv); + wrapper.init(true, paramsWithIV); + return wrapper.wrap(paddedPlaintext, inOff, paddedPlaintext.length); + } + + } + + public byte[] unwrap(byte[] in, int inOff, int inLen) + throws InvalidCipherTextException + { + if (forWrapping) + { + throw new IllegalStateException("not set for unwrapping"); + } + + int n = inLen / 8; + + if ((n * 8) != inLen) + { + throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes"); + } + + if (n == 1) + { + throw new InvalidCipherTextException("unwrap data must be at least 16 bytes"); + } + + byte[] relevantCiphertext = new byte[inLen]; + System.arraycopy(in, inOff, relevantCiphertext, 0, inLen); + byte[] decrypted = new byte[inLen]; + byte[] paddedPlaintext; + + if (n == 2) + { + // When there are exactly two 64-bit blocks of ciphertext, + // they are decrypted as a single block using AES in ECB. + engine.init(false, param); + for (int i = 0; i < relevantCiphertext.length; i += engine.getBlockSize()) + { + engine.processBlock(relevantCiphertext, i, decrypted, i); + } + + // extract the AIV + extractedAIV = new byte[8]; + System.arraycopy(decrypted, 0, extractedAIV, 0, extractedAIV.length); + paddedPlaintext = new byte[decrypted.length - extractedAIV.length]; + System.arraycopy(decrypted, extractedAIV.length, paddedPlaintext, 0, paddedPlaintext.length); + } + else + { + // Otherwise, unwrap as per RFC 3394 but don't check IV the same way + decrypted = rfc3394UnwrapNoIvCheck(in, inOff, inLen); + paddedPlaintext = decrypted; + } + + // Decompose the extracted AIV to the fixed portion and the MLI + byte[] extractedHighOrderAIV = new byte[4]; + byte[] mliBytes = new byte[4]; + System.arraycopy(extractedAIV, 0, extractedHighOrderAIV, 0, extractedHighOrderAIV.length); + System.arraycopy(extractedAIV, extractedHighOrderAIV.length, mliBytes, 0, mliBytes.length); + int mli = Pack.bigEndianToInt(mliBytes, 0); + + // Even if a check fails we still continue and check everything + // else in order to avoid certain timing based side-channel attacks. + boolean isValid = true; + + // Check the fixed portion of the AIV + if (!Arrays.constantTimeAreEqual(extractedHighOrderAIV, preIV)) + { + isValid = false; + } + + // Check the MLI against the actual length + int upperBound = paddedPlaintext.length; + int lowerBound = upperBound - 8; + if (mli <= lowerBound) + { + isValid = false; + } + if (mli > upperBound) + { + isValid = false; + } + + // Check the number of padded zeros + int expectedZeros = upperBound - mli; + byte[] zeros = new byte[expectedZeros]; + byte[] pad = new byte[expectedZeros]; + System.arraycopy(paddedPlaintext, paddedPlaintext.length - expectedZeros, pad, 0, expectedZeros); + if (!Arrays.constantTimeAreEqual(pad, zeros)) + { + isValid = false; + } + + // Extract the plaintext from the padded plaintext + byte[] plaintext = new byte[mli]; + System.arraycopy(paddedPlaintext, 0, plaintext, 0, plaintext.length); + + if (!isValid) + { + throw new InvalidCipherTextException("checksum failed"); + } + + return plaintext; + } + + /** + * Performs steps 1 and 2 of the unwrap process defined in RFC 3394. + * This code is duplicated from RFC3394WrapEngine because that class + * will throw an error during unwrap because the IV won't match up. + * + * @param in + * @param inOff + * @param inLen + * @return Unwrapped data. + */ + private byte[] rfc3394UnwrapNoIvCheck(byte[] in, int inOff, int inLen) + { + byte[] iv = new byte[8]; + byte[] block = new byte[inLen - iv.length]; + byte[] a = new byte[iv.length]; + byte[] buf = new byte[8 + iv.length]; + + System.arraycopy(in, inOff, a, 0, iv.length); + System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length); + + engine.init(false, param); + + int n = inLen / 8; + n = n - 1; + + for (int j = 5; j >= 0; j--) + { + for (int i = n; i >= 1; i--) + { + System.arraycopy(a, 0, buf, 0, iv.length); + System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8); + + int t = n * j + i; + for (int k = 1; t != 0; k++) + { + byte v = (byte)t; + + buf[iv.length - k] ^= v; + + t >>>= 8; + } + + engine.processBlock(buf, 0, buf, 0); + System.arraycopy(buf, 0, a, 0, 8); + System.arraycopy(buf, 8, block, 8 * (i - 1), 8); + } + } + + // set the extracted AIV + extractedAIV = a; + + return block; + } + +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java index 0036e1c23..ff9953aa5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/Salsa20Engine.java @@ -4,17 +4,17 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.MaxBytesExceededException; import org.spongycastle.crypto.OutputLengthException; -import org.spongycastle.crypto.StreamCipher; +import org.spongycastle.crypto.SkippingStreamCipher; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; import org.spongycastle.util.Strings; /** * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005 */ public class Salsa20Engine - implements StreamCipher + implements SkippingStreamCipher { public final static int DEFAULT_ROUNDS = 20; @@ -33,7 +33,7 @@ public class Salsa20Engine */ private int index = 0; protected int[] engineState = new int[STATE_SIZE]; // state - protected int[] x = new int[STATE_SIZE] ; // internal buffer + protected int[] x = new int[STATE_SIZE] ; // internal buffer private byte[] keyStream = new byte[STATE_SIZE * 4]; // expanded state, 64 bytes private boolean initialised = false; @@ -96,15 +96,27 @@ public class Salsa20Engine + " bytes of IV"); } - if (!(ivParams.getParameters() instanceof KeyParameter)) + CipherParameters keyParam = ivParams.getParameters(); + if (keyParam == null) { - throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must include a key"); + if (!initialised) + { + throw new IllegalStateException(getAlgorithmName() + " KeyParameter can not be null for first initialisation"); + } + + setKey(null, iv); + } + else if (keyParam instanceof KeyParameter) + { + setKey(((KeyParameter)keyParam).getKey(), iv); + } + else + { + throw new IllegalArgumentException(getAlgorithmName() + " Init parameters must contain a KeyParameter (or null for re-init)"); } - KeyParameter key = (KeyParameter) ivParams.getParameters(); - - setKey(key.getKey(), iv); reset(); + initialised = true; } @@ -130,15 +142,15 @@ public class Salsa20Engine throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV"); } - if (index == 0) - { - generateKeyStream(keyStream); - advanceCounter(); - } - byte out = (byte)(keyStream[index]^in); index = (index + 1) & 63; + if (index == 0) + { + advanceCounter(); + generateKeyStream(keyStream); + } + return out; } @@ -150,7 +162,20 @@ public class Salsa20Engine } } - public void processBytes( + protected void retreatCounter() + { + if (engineState[8] == 0 && engineState[9] == 0) + { + throw new IllegalStateException("attempt to reduce counter past zero."); + } + + if (--engineState[8] == -1) + { + --engineState[9]; + } + } + + public int processBytes( byte[] in, int inOff, int len, @@ -179,15 +204,61 @@ public class Salsa20Engine for (int i = 0; i < len; i++) { + out[i + outOff] = (byte)(keyStream[index] ^ in[i + inOff]); + index = (index + 1) & 63; + if (index == 0) { - generateKeyStream(keyStream); advanceCounter(); + generateKeyStream(keyStream); } - - out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]); - index = (index + 1) & 63; } + + return len; + } + + public long skip(long numberOfBytes) + { + if (numberOfBytes >= 0) + { + for (long i = 0; i < numberOfBytes; i++) + { + index = (index + 1) & 63; + + if (index == 0) + { + advanceCounter(); + } + } + } + else + { + for (long i = 0; i > numberOfBytes; i--) + { + if (index == 0) + { + retreatCounter(); + } + + index = (index - 1) & 63; + } + } + + generateKeyStream(keyStream); + + return numberOfBytes; + } + + public long seekTo(long position) + { + reset(); + + return skip(position); + } + + public long getPosition() + { + return getCounter() * 64 + index; } public void reset() @@ -195,6 +266,13 @@ public class Salsa20Engine index = 0; resetLimitCounter(); resetCounter(); + + generateKeyStream(keyStream); + } + + protected long getCounter() + { + return ((long)engineState[9] << 32) | (engineState[8] & 0xffffffffL); } protected void resetCounter() @@ -204,43 +282,46 @@ public class Salsa20Engine protected void setKey(byte[] keyBytes, byte[] ivBytes) { - if ((keyBytes.length != 16) && (keyBytes.length != 32)) { - throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key"); - } - - int offset = 0; - byte[] constants; - - // Key - engineState[1] = Pack.littleEndianToInt(keyBytes, 0); - engineState[2] = Pack.littleEndianToInt(keyBytes, 4); - engineState[3] = Pack.littleEndianToInt(keyBytes, 8); - engineState[4] = Pack.littleEndianToInt(keyBytes, 12); - - if (keyBytes.length == 32) + if (keyBytes != null) { - constants = sigma; - offset = 16; - } - else - { - constants = tau; - } + if ((keyBytes.length != 16) && (keyBytes.length != 32)) + { + throw new IllegalArgumentException(getAlgorithmName() + " requires 128 bit or 256 bit key"); + } - engineState[11] = Pack.littleEndianToInt(keyBytes, offset); - engineState[12] = Pack.littleEndianToInt(keyBytes, offset+4); - engineState[13] = Pack.littleEndianToInt(keyBytes, offset+8); - engineState[14] = Pack.littleEndianToInt(keyBytes, offset+12); + // Key + engineState[1] = Pack.littleEndianToInt(keyBytes, 0); + engineState[2] = Pack.littleEndianToInt(keyBytes, 4); + engineState[3] = Pack.littleEndianToInt(keyBytes, 8); + engineState[4] = Pack.littleEndianToInt(keyBytes, 12); - engineState[0 ] = Pack.littleEndianToInt(constants, 0); - engineState[5 ] = Pack.littleEndianToInt(constants, 4); - engineState[10] = Pack.littleEndianToInt(constants, 8); - engineState[15] = Pack.littleEndianToInt(constants, 12); + byte[] constants; + int offset; + if (keyBytes.length == 32) + { + constants = sigma; + offset = 16; + } + else + { + constants = tau; + offset = 0; + } + + engineState[11] = Pack.littleEndianToInt(keyBytes, offset); + engineState[12] = Pack.littleEndianToInt(keyBytes, offset + 4); + engineState[13] = Pack.littleEndianToInt(keyBytes, offset + 8); + engineState[14] = Pack.littleEndianToInt(keyBytes, offset + 12); + + engineState[0 ] = Pack.littleEndianToInt(constants, 0); + engineState[5 ] = Pack.littleEndianToInt(constants, 4); + engineState[10] = Pack.littleEndianToInt(constants, 8); + engineState[15] = Pack.littleEndianToInt(constants, 12); + } // IV engineState[6] = Pack.littleEndianToInt(ivBytes, 0); engineState[7] = Pack.littleEndianToInt(ivBytes, 4); - resetCounter(); } protected void generateKeyStream(byte[] output) @@ -253,18 +334,19 @@ public class Salsa20Engine * Salsa20 function * * @param input input data - * - * @return keystream */ public static void salsaCore(int rounds, int[] input, int[] x) { - if (input.length != 16) { + if (input.length != 16) + { throw new IllegalArgumentException(); } - if (x.length != 16) { + if (x.length != 16) + { throw new IllegalArgumentException(); } - if (rounds % 2 != 0) { + if (rounds % 2 != 0) + { throw new IllegalArgumentException("Number of rounds must be even"); } @@ -287,39 +369,39 @@ public class Salsa20Engine for (int i = rounds; i > 0; i -= 2) { - x04 ^= rotl((x00+x12), 7); - x08 ^= rotl((x04+x00), 9); - x12 ^= rotl((x08+x04),13); - x00 ^= rotl((x12+x08),18); - x09 ^= rotl((x05+x01), 7); - x13 ^= rotl((x09+x05), 9); - x01 ^= rotl((x13+x09),13); - x05 ^= rotl((x01+x13),18); - x14 ^= rotl((x10+x06), 7); - x02 ^= rotl((x14+x10), 9); - x06 ^= rotl((x02+x14),13); - x10 ^= rotl((x06+x02),18); - x03 ^= rotl((x15+x11), 7); - x07 ^= rotl((x03+x15), 9); - x11 ^= rotl((x07+x03),13); - x15 ^= rotl((x11+x07),18); + x04 ^= rotl(x00 + x12, 7); + x08 ^= rotl(x04 + x00, 9); + x12 ^= rotl(x08 + x04, 13); + x00 ^= rotl(x12 + x08, 18); + x09 ^= rotl(x05 + x01, 7); + x13 ^= rotl(x09 + x05, 9); + x01 ^= rotl(x13 + x09, 13); + x05 ^= rotl(x01 + x13, 18); + x14 ^= rotl(x10 + x06, 7); + x02 ^= rotl(x14 + x10, 9); + x06 ^= rotl(x02 + x14, 13); + x10 ^= rotl(x06 + x02, 18); + x03 ^= rotl(x15 + x11, 7); + x07 ^= rotl(x03 + x15, 9); + x11 ^= rotl(x07 + x03, 13); + x15 ^= rotl(x11 + x07, 18); - x01 ^= rotl((x00+x03), 7); - x02 ^= rotl((x01+x00), 9); - x03 ^= rotl((x02+x01),13); - x00 ^= rotl((x03+x02),18); - x06 ^= rotl((x05+x04), 7); - x07 ^= rotl((x06+x05), 9); - x04 ^= rotl((x07+x06),13); - x05 ^= rotl((x04+x07),18); - x11 ^= rotl((x10+x09), 7); - x08 ^= rotl((x11+x10), 9); - x09 ^= rotl((x08+x11),13); - x10 ^= rotl((x09+x08),18); - x12 ^= rotl((x15+x14), 7); - x13 ^= rotl((x12+x15), 9); - x14 ^= rotl((x13+x12),13); - x15 ^= rotl((x14+x13),18); + x01 ^= rotl(x00 + x03, 7); + x02 ^= rotl(x01 + x00, 9); + x03 ^= rotl(x02 + x01, 13); + x00 ^= rotl(x03 + x02, 18); + x06 ^= rotl(x05 + x04, 7); + x07 ^= rotl(x06 + x05, 9); + x04 ^= rotl(x07 + x06, 13); + x05 ^= rotl(x04 + x07, 18); + x11 ^= rotl(x10 + x09, 7); + x08 ^= rotl(x11 + x10, 9); + x09 ^= rotl(x08 + x11, 13); + x10 ^= rotl(x09 + x08, 18); + x12 ^= rotl(x15 + x14, 7); + x13 ^= rotl(x12 + x15, 9); + x14 ^= rotl(x13 + x12, 13); + x15 ^= rotl(x14 + x13, 18); } x[ 0] = x00 + input[ 0]; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java index e96203b6b..944f0ae59 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/SerpentEngine.java @@ -12,7 +12,7 @@ import org.spongycastle.crypto.params.KeyParameter; * secure as three-key triple-DES. ** Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a - * candidate algorithm for the NIST AES Quest.> + * candidate algorithm for the NIST AES Quest. *
* For full details see the The Serpent home page */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java index a5d59308b..40e08b9b1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/ThreefishEngine.java @@ -9,13 +9,13 @@ import org.spongycastle.crypto.params.TweakableBlockCipherParameters; /** * Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block * sizes. - *
+ ** This is the 1.3 version of Threefish defined in the Skein hash function submission to the NIST * SHA-3 competition in October 2010. - *
+ ** Threefish was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker. - *
+ ** This implementation inlines all round functions, unrolls 8 rounds, and uses 1.2k of static tables * to speed up key schedule injection.
* 2 x block size state is retained by each cipher instance. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java index b4a3f23c3..f1a4a5640 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/VMPCEngine.java @@ -91,7 +91,7 @@ public class VMPCEngine implements StreamCipher n = 0; } - public void processBytes(byte[] in, int inOff, int len, byte[] out, + public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) { if ((inOff + len) > in.length) @@ -117,6 +117,8 @@ public class VMPCEngine implements StreamCipher // xor out[i + outOff] = (byte) (in[i + inOff] ^ z); } + + return len; } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java index 0acbf101e..f70022b93 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/engines/XSalsa20Engine.java @@ -1,6 +1,6 @@ package org.spongycastle.crypto.engines; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce. @@ -9,7 +9,6 @@ import org.spongycastle.crypto.util.Pack; */ public class XSalsa20Engine extends Salsa20Engine { - public String getAlgorithmName() { return "XSalsa20"; @@ -27,6 +26,11 @@ public class XSalsa20Engine extends Salsa20Engine */ protected void setKey(byte[] keyBytes, byte[] ivBytes) { + if (keyBytes == null) + { + throw new IllegalArgumentException(getAlgorithmName() + " doesn't support re-init with null key"); + } + if (keyBytes.length != 32) { throw new IllegalArgumentException(getAlgorithmName() + " requires a 256 bit key"); @@ -57,9 +61,5 @@ public class XSalsa20Engine extends Salsa20Engine // Last 64 bits of input IV engineState[6] = Pack.littleEndianToInt(ivBytes, 16); engineState[7] = Pack.littleEndianToInt(ivBytes, 20); - - // Counter reset - resetCounter(); } - } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java index d9e3a60da..f05ffbdf2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/examples/DESExample.java @@ -41,9 +41,11 @@ import org.spongycastle.util.encoders.Hex; ** When decrypting; + *
*
*- the infile is expected to be the 60 character wide base64 * encoded file *
- the keyfile is expected to be a base64 encoded file + *
* This example shows how to use the light-weight API, DES and * the filesystem for message encryption and decryption. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java index fc0faf50b..0d1577cd4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/BaseKDFBytesGenerator.java @@ -6,7 +6,7 @@ import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.DigestDerivationFunction; import org.spongycastle.crypto.params.ISO18033KDFParameters; import org.spongycastle.crypto.params.KDFParameters; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java new file mode 100644 index 000000000..e5186b9ad --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupKeyPairGenerator.java @@ -0,0 +1,63 @@ +package org.spongycastle.crypto.generators; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator; +import org.spongycastle.crypto.KeyGenerationParameters; +import org.spongycastle.crypto.params.CramerShoupKeyGenerationParameters; +import org.spongycastle.crypto.params.CramerShoupParameters; +import org.spongycastle.crypto.params.CramerShoupPrivateKeyParameters; +import org.spongycastle.crypto.params.CramerShoupPublicKeyParameters; +import org.spongycastle.util.BigIntegers; + +/** + * a Cramer Shoup key pair generator + * + */ +public class CramerShoupKeyPairGenerator implements AsymmetricCipherKeyPairGenerator { + + private static final BigInteger ONE = BigInteger.valueOf(1); + + private CramerShoupKeyGenerationParameters param; + + public void init(KeyGenerationParameters param) { + this.param = (CramerShoupKeyGenerationParameters) param; + } + + public AsymmetricCipherKeyPair generateKeyPair() { + CramerShoupParameters csParams = param.getParameters(); + + CramerShoupPrivateKeyParameters sk = generatePrivateKey(param.getRandom(), csParams); + CramerShoupPublicKeyParameters pk = calculatePublicKey(csParams, sk); + sk.setPk(pk); + + return new AsymmetricCipherKeyPair(pk, sk); + } + + private BigInteger generateRandomElement(BigInteger p, SecureRandom random) { + return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random); + } + + private CramerShoupPrivateKeyParameters generatePrivateKey(SecureRandom random, CramerShoupParameters csParams){ + BigInteger p = csParams.getP(); + CramerShoupPrivateKeyParameters key = new CramerShoupPrivateKeyParameters(csParams, + generateRandomElement(p, random), generateRandomElement(p, random), + generateRandomElement(p, random), generateRandomElement(p, random), + generateRandomElement(p, random)); + return key; + } + + private CramerShoupPublicKeyParameters calculatePublicKey(CramerShoupParameters csParams, CramerShoupPrivateKeyParameters sk) { + BigInteger g1 = csParams.getG1(); + BigInteger g2 = csParams.getG2(); + BigInteger p = csParams.getP(); + + BigInteger c = g1.modPow(sk.getX1(), p).multiply(g2.modPow(sk.getX2(), p)); + BigInteger d = g1.modPow(sk.getY1(), p).multiply(g2.modPow(sk.getY2(), p)); + BigInteger h = g1.modPow(sk.getZ(), p); + + return new CramerShoupPublicKeyParameters(csParams, c, d, h); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java new file mode 100644 index 000000000..b7b32a3bd --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/CramerShoupParametersGenerator.java @@ -0,0 +1,123 @@ +package org.spongycastle.crypto.generators; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.spongycastle.crypto.digests.SHA256Digest; +import org.spongycastle.crypto.params.CramerShoupParameters; +import org.spongycastle.crypto.params.DHParameters; +import org.spongycastle.util.BigIntegers; + +public class CramerShoupParametersGenerator +{ + private static final BigInteger ONE = BigInteger.valueOf(1); + + private int size; + private int certainty; + private SecureRandom random; + + /** + * Initialise the parameters generator. + * + * @param size bit length for the prime p + * @param certainty a measure of the uncertainty that the caller is willing to tolerate: + * the probability that the generated modulus is prime exceeds (1 - 1/2^certainty). + * The execution time of this method is proportional to the value of this parameter. + * @param random a source of randomness + */ + public void init(int size, int certainty, SecureRandom random) + { + this.size = size; + this.certainty = certainty; + this.random = random; + } + + /** + * which generates the p and g values from the given parameters, returning + * the CramerShoupParameters object. + *
+ * Note: can take a while... + */ + public CramerShoupParameters generateParameters() + { + // + // find a safe prime p where p = 2*q + 1, where p and q are prime. + // + BigInteger[] safePrimes = ParametersHelper.generateSafePrimes(size, certainty, random); + +// BigInteger p = safePrimes[0]; + BigInteger q = safePrimes[1]; + BigInteger g1 = ParametersHelper.selectGenerator(q, random); + BigInteger g2 = ParametersHelper.selectGenerator(q, random); + while (g1.equals(g2)) + { + g2 = ParametersHelper.selectGenerator(q, random); + } + + return new CramerShoupParameters(q, g1, g2, new SHA256Digest()); + } + + public CramerShoupParameters generateParameters(DHParameters dhParams) + { + BigInteger p = dhParams.getP(); + BigInteger g1 = dhParams.getG(); + + // now we just need a second generator + BigInteger g2 = ParametersHelper.selectGenerator(p, random); + while (g1.equals(g2)) + { + g2 = ParametersHelper.selectGenerator(p, random); + } + + return new CramerShoupParameters(p, g1, g2, new SHA256Digest()); + } + + private static class ParametersHelper + { + + private static final BigInteger TWO = BigInteger.valueOf(2); + + /* + * Finds a pair of prime BigInteger's {p, q: p = 2q + 1} + * + * (see: Handbook of Applied Cryptography 4.86) + */ + static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random) + { + BigInteger p, q; + int qLength = size - 1; + + for (; ; ) + { + q = new BigInteger(qLength, 2, random); + p = q.shiftLeft(1).add(ONE); + if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty))) + { + break; + } + } + + return new BigInteger[]{p, q}; + } + + static BigInteger selectGenerator(BigInteger p, SecureRandom random) + { + BigInteger pMinusTwo = p.subtract(TWO); + BigInteger g; + + /* + * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81) + */ + do + { + BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random); + + g = h.modPow(TWO, p); + } + while (g.equals(ONE)); + + return g; + } + } + +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java index b987e5b1c..6982d222c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHKeyGeneratorHelper.java @@ -4,6 +4,7 @@ import java.math.BigInteger; import java.security.SecureRandom; import org.spongycastle.crypto.params.DHParameters; +import org.spongycastle.math.ec.WNafUtil; import org.spongycastle.util.BigIntegers; class DHKeyGeneratorHelper @@ -19,12 +20,19 @@ class DHKeyGeneratorHelper BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random) { - BigInteger p = dhParams.getP(); int limit = dhParams.getL(); if (limit != 0) { - return new BigInteger(limit, random).setBit(limit - 1); + int minWeight = limit >>> 2; + for (;;) + { + BigInteger x = new BigInteger(limit, random).setBit(limit - 1); + if (WNafUtil.getNafWeight(x) >= minWeight) + { + return x; + } + } } BigInteger min = TWO; @@ -34,14 +42,22 @@ class DHKeyGeneratorHelper min = ONE.shiftLeft(m - 1); } - BigInteger max = p.subtract(TWO); BigInteger q = dhParams.getQ(); - if (q != null) + if (q == null) { - max = q.subtract(TWO); + q = dhParams.getP(); } + BigInteger max = q.subtract(TWO); - return BigIntegers.createRandomInRange(min, max, random); + int minWeight = max.bitLength() >>> 2; + for (;;) + { + BigInteger x = BigIntegers.createRandomInRange(min, max, random); + if (WNafUtil.getNafWeight(x) >= minWeight) + { + return x; + } + } } BigInteger calculatePublic(DHParameters dhParams, BigInteger x) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java index af6db5012..248131918 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DHParametersHelper.java @@ -3,6 +3,7 @@ package org.spongycastle.crypto.generators; import java.math.BigInteger; import java.security.SecureRandom; +import org.spongycastle.math.ec.WNafUtil; import org.spongycastle.util.BigIntegers; class DHParametersHelper @@ -19,6 +20,7 @@ class DHParametersHelper { BigInteger p, q; int qLength = size - 1; + int minWeight = size >>> 2; for (;;) { @@ -27,10 +29,28 @@ class DHParametersHelper // p <- 2q + 1 p = q.shiftLeft(1).add(ONE); - if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty))) + if (!p.isProbablePrime(certainty)) { - break; + continue; } + + if (certainty > 2 && !q.isProbablePrime(certainty - 2)) + { + continue; + } + + /* + * Require a minimum weight of the NAF representation, since low-weight primes may be + * weak against a version of the number-field-sieve for the discrete-logarithm-problem. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtil.getNafWeight(p) < minWeight) + { + continue; + } + + break; } return new BigInteger[] { p, q }; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java index 609f2f3a1..01c3b26af 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAKeyPairGenerator.java @@ -1,5 +1,8 @@ package org.spongycastle.crypto.generators; +import java.math.BigInteger; +import java.security.SecureRandom; + import org.spongycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.spongycastle.crypto.KeyGenerationParameters; @@ -7,11 +10,9 @@ import org.spongycastle.crypto.params.DSAKeyGenerationParameters; import org.spongycastle.crypto.params.DSAParameters; import org.spongycastle.crypto.params.DSAPrivateKeyParameters; import org.spongycastle.crypto.params.DSAPublicKeyParameters; +import org.spongycastle.math.ec.WNafUtil; import org.spongycastle.util.BigIntegers; -import java.math.BigInteger; -import java.security.SecureRandom; - /** * a DSA key pair generator. * @@ -45,13 +46,20 @@ public class DSAKeyPairGenerator private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random) { - // TODO Prefer this method? (change test cases that used fixed random) - // B.1.1 Key Pair Generation Using Extra Random Bits -// BigInteger c = new BigInteger(q.bitLength() + 64, random); -// return c.mod(q.subtract(ONE)).add(ONE); - // B.1.2 Key Pair Generation by Testing Candidates - return BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random); + int minWeight = q.bitLength() >>> 2; + for (;;) + { + // TODO Prefer this method? (change test cases that used fixed random) + // B.1.1 Key Pair Generation Using Extra Random Bits +// BigInteger x = new BigInteger(q.bitLength() + 64, random).mod(q.subtract(ONE)).add(ONE); + + BigInteger x = BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random); + if (WNafUtil.getNafWeight(x) >= minWeight) + { + return x; + } + } } private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java index d89a776eb..b00130fc7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/DSAParametersGenerator.java @@ -42,7 +42,7 @@ public class DSAParametersGenerator /** * initialise the key generator. * - * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments) + * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments) * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80). * @param random random byte source. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java index 1b59a7b60..62b12b9a3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/ECKeyPairGenerator.java @@ -11,7 +11,10 @@ import org.spongycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; +import org.spongycastle.math.ec.WNafUtil; public class ECKeyPairGenerator implements AsymmetricCipherKeyPairGenerator, ECConstants @@ -40,19 +43,42 @@ public class ECKeyPairGenerator public AsymmetricCipherKeyPair generateKeyPair() { BigInteger n = params.getN(); - int nBitLength = n.bitLength(); - BigInteger d; + int nBitLength = n.bitLength(); + int minWeight = nBitLength >>> 2; - do + BigInteger d; + for (;;) { d = new BigInteger(nBitLength, random); - } - while (d.equals(ZERO) || (d.compareTo(n) >= 0)); - ECPoint Q = params.getG().multiply(d); + if (d.compareTo(TWO) < 0 || (d.compareTo(n) >= 0)) + { + continue; + } + + /* + * Require a minimum weight of the NAF representation, since low-weight primes may be + * weak against a version of the number-field-sieve for the discrete-logarithm-problem. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtil.getNafWeight(d) < minWeight) + { + continue; + } + + break; + } + + ECPoint Q = createBasePointMultiplier().multiply(params.getG(), d); return new AsymmetricCipherKeyPair( new ECPublicKeyParameters(Q, params), new ECPrivateKeyParameters(d, params)); } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java index 55bcdbca9..2929828b0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/GOST3410KeyPairGenerator.java @@ -7,6 +7,7 @@ import org.spongycastle.crypto.params.GOST3410KeyGenerationParameters; import org.spongycastle.crypto.params.GOST3410Parameters; import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters; import org.spongycastle.crypto.params.GOST3410PublicKeyParameters; +import org.spongycastle.math.ec.WNafUtil; import java.math.BigInteger; import java.security.SecureRandom; @@ -19,8 +20,6 @@ import java.security.SecureRandom; public class GOST3410KeyPairGenerator implements AsymmetricCipherKeyPairGenerator { - private static final BigInteger ZERO = BigInteger.valueOf(0); - private GOST3410KeyGenerationParameters param; public void init( @@ -39,11 +38,29 @@ public class GOST3410KeyPairGenerator p = GOST3410Params.getP(); a = GOST3410Params.getA(); - do + int minWeight = 64; + for (;;) { x = new BigInteger(256, random); + + if (x.signum() < 1 || x.compareTo(q) >= 0) + { + continue; + } + + /* + * Require a minimum weight of the NAF representation, since low-weight primes may be + * weak against a version of the number-field-sieve for the discrete-logarithm-problem. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtil.getNafWeight(x) < minWeight) + { + continue; + } + + break; } - while (x.equals(ZERO) || x.compareTo(q) >= 0); // // calculate the public key. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java index 9ec7987e1..fbeeca61d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/HKDFBytesGenerator.java @@ -11,7 +11,7 @@ import org.spongycastle.crypto.params.KeyParameter; /** * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) implemented * according to IETF RFC 5869, May 2010 as specified by H. Krawczyk, IBM - * Research & P. Eronen, Nokia. It uses a HMac internally to compute de OKM + * Research & P. Eronen, Nokia. It uses a HMac internally to compute de OKM * (output keying material) and is likely to have better security properties * than KDF's based on just a hash function. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java index 6341b16f9..fd5403547 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/KDFCounterBytesGenerator.java @@ -11,6 +11,31 @@ import org.spongycastle.crypto.params.KeyParameter; /** * This KDF has been defined by the publicly available NIST SP 800-108 specification. + * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways. + * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData. + *+ *
+ * + *- 1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)
+ *- 2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData
+ *- 3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:
+ *- 3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:
+ *- 3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.
+ *+ * This function must be called with the following KDFCounterParameters(): + * - KI
+ * Resulting function calls assuming an 8 bit counter. + *
+ * - The part of the fixedInputData that comes BEFORE the counter OR null
+ * - the part of the fixedInputData that comes AFTER the counter OR null
+ * - the length of the counter in bits (not bytes) + *+ *
*/ public class KDFCounterBytesGenerator implements MacDerivationFunction @@ -27,7 +52,8 @@ public class KDFCounterBytesGenerator private final int h; // fields set by init - private byte[] fixedInputData; + private byte[] fixedInputDataCtrPrefix; + private byte[] fixedInputData_afterCtr; private int maxSizeExcl; // ios is i defined as an octet string (the binary representation) private byte[] ios; @@ -61,7 +87,8 @@ public class KDFCounterBytesGenerator // --- set arguments --- - this.fixedInputData = kdfParams.getFixedInputData(); + this.fixedInputDataCtrPrefix = kdfParams.getFixedInputDataCounterPrefix(); + this.fixedInputData_afterCtr = kdfParams.getFixedInputDataCounterSuffix(); int r = kdfParams.getR(); this.ios = new byte[r / 8]; @@ -145,8 +172,9 @@ public class KDFCounterBytesGenerator // special case for K(0): K(0) is empty, so no update + prf.update(fixedInputDataCtrPrefix, 0, fixedInputDataCtrPrefix.length); prf.update(ios, 0, ios.length); - prf.update(fixedInputData, 0, fixedInputData.length); + prf.update(fixedInputData_afterCtr, 0, fixedInputData_afterCtr.length); prf.doFinal(k, 0); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java index 5eebc497f..4c5c148a7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/Poly1305KeyGenerator.java @@ -53,7 +53,7 @@ public class Poly1305KeyGenerator *- 1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8);
+ *- 2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8);
+ *- 3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8);
+ *- 3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);
+ *- 3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8);
+ *r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}) * * - * @param a 32 byte key valuek[0] ... k[15], r[0] ... r[15]
+ * @param key a 32 byte key valuek[0] ... k[15], r[0] ... r[15]
*/ public static void clamp(byte[] key) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java index 0708ec729..354eccd23 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/RSAKeyPairGenerator.java @@ -6,6 +6,7 @@ import org.spongycastle.crypto.KeyGenerationParameters; import org.spongycastle.crypto.params.RSAKeyGenerationParameters; import org.spongycastle.crypto.params.RSAKeyParameters; import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.spongycastle.math.ec.WNafUtil; import java.math.BigInteger; @@ -19,83 +20,43 @@ public class RSAKeyPairGenerator private RSAKeyGenerationParameters param; - public void init( - KeyGenerationParameters param) + public void init(KeyGenerationParameters param) { this.param = (RSAKeyGenerationParameters)param; } public AsymmetricCipherKeyPair generateKeyPair() { - BigInteger p, q, n, d, e, pSub1, qSub1, phi; + BigInteger p, q, n, d, e, pSub1, qSub1, phi; // // p and q values should have a length of half the strength in bits // int strength = param.getStrength(); - int pbitlength = (strength + 1) / 2; - int qbitlength = strength - pbitlength; + int qBitlength = strength >>> 1; + int pBitlength = strength - qBitlength; int mindiffbits = strength / 3; + int minWeight = strength >>> 2; e = param.getPublicExponent(); // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes) // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm") - // - // generate p, prime and (p-1) relatively prime to e - // - for (;;) - { - p = new BigInteger(pbitlength, 1, param.getRandom()); - - if (p.mod(e).equals(ONE)) - { - continue; - } - - if (!p.isProbablePrime(param.getCertainty())) - { - continue; - } - - if (e.gcd(p.subtract(ONE)).equals(ONE)) - { - break; - } - } + p = chooseRandomPrime(pBitlength, e); // // generate a modulus of the required length // for (;;) { - // generate q, prime and (q-1) relatively prime to e, - // and not equal to p - // - for (;;) - { - q = new BigInteger(qbitlength, 1, param.getRandom()); + q = chooseRandomPrime(qBitlength, e); - if (q.subtract(p).abs().bitLength() < mindiffbits) - { - continue; - } - - if (q.mod(e).equals(ONE)) - { - continue; - } - - if (!q.isProbablePrime(param.getCertainty())) - { - continue; - } - - if (e.gcd(q.subtract(ONE)).equals(ONE)) - { - break; - } + // p and q should not be too close together (or equal!) + BigInteger diff = q.subtract(p).abs(); + if (diff.bitLength() < mindiffbits) + { + continue; } // @@ -103,16 +64,29 @@ public class RSAKeyPairGenerator // n = p.multiply(q); - if (n.bitLength() == param.getStrength()) + if (n.bitLength() != strength) { - break; + // + // if we get here our primes aren't big enough, make the largest + // of the two p and try again + // + p = p.max(q); + continue; } - // - // if we get here our primes aren't big enough, make the largest - // of the two p and try again - // - p = p.max(q); + /* + * Require a minimum weight of the NAF representation, since low-weight composites may + * be weak against a version of the number-field-sieve for factoring. + * + * See "The number field sieve for integers of low weight", Oliver Schirokauer. + */ + if (WNafUtil.getNafWeight(n) < minWeight) + { + p = chooseRandomPrime(pBitlength, e); + continue; + } + + break; } if (p.compareTo(q) < 0) @@ -134,14 +108,46 @@ public class RSAKeyPairGenerator // // calculate the CRT factors // - BigInteger dP, dQ, qInv; + BigInteger dP, dQ, qInv; dP = d.remainder(pSub1); dQ = d.remainder(qSub1); qInv = q.modInverse(p); return new AsymmetricCipherKeyPair( - new RSAKeyParameters(false, n, e), - new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + new RSAKeyParameters(false, n, e), + new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv)); + } + + /** + * Choose a random prime value for use with RSA + * + * @param bitlength the bit-length of the returned prime + * @param e the RSA public exponent + * @return a prime p, with (p-1) relatively prime to e + */ + protected BigInteger chooseRandomPrime(int bitlength, BigInteger e) + { + for (;;) + { + BigInteger p = new BigInteger(bitlength, 1, param.getRandom()); + + if (p.mod(e).equals(ONE)) + { + continue; + } + + if (!p.isProbablePrime(param.getCertainty())) + { + continue; + } + + if (!e.gcd(p.subtract(ONE)).equals(ONE)) + { + continue; + } + + return p; + } } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java index c199adbf2..58d59bafa 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/generators/SCrypt.java @@ -4,14 +4,65 @@ import org.spongycastle.crypto.PBEParametersGenerator; import org.spongycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.engines.Salsa20Engine; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; +/** + * Implementation of the scrypt a password-based key derivation function. + *+ * Scrypt was created by Colin Percival and is specified in draft-josefsson-scrypt-kd + * + */ public class SCrypt { - // TODO Validate arguments + /** + * Generate a key using the scrypt key derivation function. + * + * @param P the bytes of the pass phrase. + * @param S the salt to use for this invocation. + * @param N CPU/Memory cost parameter. Must be larger than 1, a power of 2 and less than + *
+ *2^(128 * r / 8)
. + * @param r the block size, must be >= 1. + * @param p Parallelization parameter. Must be a positive integer less than or equal to + *Integer.MAX_VALUE / (128 * r * 8)
. + * + * @param dkLen the length of the key to generate. + * @return the generated key. + */ public static byte[] generate(byte[] P, byte[] S, int N, int r, int p, int dkLen) { + if (P== null) + { + throw new IllegalArgumentException("Passphrase P must be provided."); + } + if (S == null) + { + throw new IllegalArgumentException("Salt S must be provided."); + } + if (N <= 1) + { + throw new IllegalArgumentException("Cost parameter N must be > 1."); + } + // Only value of r that cost (as an int) could be exceeded for is 1 + if (r == 1 && N > 65536) + { + throw new IllegalArgumentException("Cost parameter N must be > 1 and < 65536."); + } + if (r < 1) + { + throw new IllegalArgumentException("Block size r must be >= 1."); + } + int maxParallel = Integer.MAX_VALUE / (128 * r * 8); + if (p < 1 || p > maxParallel) + { + throw new IllegalArgumentException("Parallelisation parameter p must be >= 1 and <= " + maxParallel + + " (based on block size r of " + r + ")"); + } + if (dkLen < 1) + { + throw new IllegalArgumentException("Generated key length dkLen must be >= 1."); + } return MFcrypt(P, S, N, r, p, dkLen); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java new file mode 100644 index 000000000..c621c6b15 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherIOException.java @@ -0,0 +1,26 @@ +package org.spongycastle.crypto.io; + +import java.io.IOException; + +/** + * {@link IOException} wrapper around an exception indicating a problem with the use of a cipher. + */ +public class CipherIOException + extends IOException +{ + private static final long serialVersionUID = 1L; + + private final Throwable cause; + + public CipherIOException(String message, Throwable cause) + { + super(message); + + this.cause = cause; + } + + public Throwable getCause() + { + return cause; + } +} \ No newline at end of file diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java index 4b5b677ea..625e6659a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherInputStream.java @@ -6,14 +6,16 @@ import java.io.InputStream; import org.spongycastle.crypto.BufferedBlockCipher; import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.SkippingCipher; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.modes.AEADBlockCipher; +import org.spongycastle.util.Arrays; /** * A CipherInputStream is composed of an InputStream and a cipher so that read() methods return data * that are read in from the underlying InputStream but have been additionally processed by the * Cipher. The cipher must be fully initialized before being used by a CipherInputStream. - ** For example, if the Cipher is initialized for decryption, the * CipherInputStream will attempt to read in data and decrypt them, * before returning the decrypted data. @@ -21,18 +23,24 @@ import org.spongycastle.crypto.modes.AEADBlockCipher; public class CipherInputStream extends FilterInputStream { + private static final int INPUT_BUF_SIZE = 2048; + + private SkippingCipher skippingCipher; + private byte[] inBuf; + private BufferedBlockCipher bufferedBlockCipher; private StreamCipher streamCipher; private AEADBlockCipher aeadBlockCipher; - private final byte[] buf; - private final byte[] inBuf; + private byte[] buf; + private byte[] markBuf; + private int bufOff; private int maxBuf; private boolean finalized; - - private static final int INPUT_BUF_SIZE = 2048; + private long markPosition; + private int markBufOff; /** * Constructs a CipherInputStream from an InputStream and a @@ -42,37 +50,73 @@ public class CipherInputStream InputStream is, BufferedBlockCipher cipher) { - super(is); - - this.bufferedBlockCipher = cipher; - - buf = new byte[cipher.getOutputSize(INPUT_BUF_SIZE)]; - inBuf = new byte[INPUT_BUF_SIZE]; + this(is, cipher, INPUT_BUF_SIZE); } + /** + * Constructs a CipherInputStream from an InputStream and a StreamCipher. + */ public CipherInputStream( InputStream is, StreamCipher cipher) { - super(is); - - this.streamCipher = cipher; - - buf = new byte[INPUT_BUF_SIZE]; - inBuf = new byte[INPUT_BUF_SIZE]; + this(is, cipher, INPUT_BUF_SIZE); } /** * Constructs a CipherInputStream from an InputStream and an AEADBlockCipher. */ - public CipherInputStream(InputStream is, AEADBlockCipher cipher) + public CipherInputStream( + InputStream is, + AEADBlockCipher cipher) + { + this(is, cipher, INPUT_BUF_SIZE); + } + + /** + * Constructs a CipherInputStream from an InputStream, a + * BufferedBlockCipher, and a specified internal buffer size. + */ + public CipherInputStream( + InputStream is, + BufferedBlockCipher cipher, + int bufSize) + { + super(is); + + this.bufferedBlockCipher = cipher; + this.inBuf = new byte[bufSize]; + this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null; + } + + /** + * Constructs a CipherInputStream from an InputStream, a StreamCipher, and a specified internal buffer size. + */ + public CipherInputStream( + InputStream is, + StreamCipher cipher, + int bufSize) + { + super(is); + + this.streamCipher = cipher; + this.inBuf = new byte[bufSize]; + this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null; + } + + /** + * Constructs a CipherInputStream from an InputStream, an AEADBlockCipher, and a specified internal buffer size. + */ + public CipherInputStream( + InputStream is, + AEADBlockCipher cipher, + int bufSize) { super(is); this.aeadBlockCipher = cipher; - - buf = new byte[cipher.getOutputSize(INPUT_BUF_SIZE)]; - inBuf = new byte[INPUT_BUF_SIZE]; + this.inBuf = new byte[bufSize]; + this.skippingCipher = (cipher instanceof SkippingCipher) ? (SkippingCipher)cipher : null; } /** @@ -108,6 +152,7 @@ public class CipherInputStream try { + ensureCapacity(read, false); if (bufferedBlockCipher != null) { maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, read, buf, 0); @@ -124,7 +169,7 @@ public class CipherInputStream } catch (Exception e) { - throw new IOException("Error processing stream " + e); + throw new CipherIOException("Error processing stream ", e); } } return maxBuf; @@ -136,6 +181,7 @@ public class CipherInputStream try { finalized = true; + ensureCapacity(0, true); if (bufferedBlockCipher != null) { maxBuf = bufferedBlockCipher.doFinal(buf, 0); @@ -162,9 +208,9 @@ public class CipherInputStream /** * Reads data from the underlying stream and processes it with the cipher until the cipher * outputs data, and returns the next available byte. - *
+ ** If the underlying stream is exhausted by this call, the cipher will be finalised. - * + *
* @throws IOException if there was an error closing the input stream. * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails). @@ -186,9 +232,9 @@ public class CipherInputStream /** * Reads data from the underlying stream and processes it with the cipher until the cipher * outputs data, and then returns up tob.length
bytes in the provided array. - * + ** If the underlying stream is exhausted by this call, the cipher will be finalised. - * + *
* @param b the buffer into which the data is read. * @return the total number of bytes read into the buffer, or-1
if there is no * more data because the end of the stream has been reached. @@ -206,9 +252,9 @@ public class CipherInputStream /** * Reads data from the underlying stream and processes it with the cipher until the cipher * outputs data, and then returns up tolen
bytes in the provided array. - * + ** If the underlying stream is exhausted by this call, the cipher will be finalised. - * + *
* @param b the buffer into which the data is read. * @param off the start offset in the destination arrayb
* @param len the maximum number of bytes read. @@ -247,9 +293,36 @@ public class CipherInputStream return 0; } - int skip = (int)Math.min(n, available()); - bufOff += skip; - return skip; + if (skippingCipher != null) + { + int avail = available(); + if (n <= avail) + { + bufOff += n; + + return n; + } + + bufOff = maxBuf; + + long skip = in.skip(n - avail); + + long cSkip = skippingCipher.skip(skip); + + if (skip != cSkip) + { + throw new IOException("Unable to skip cipher " + skip + " bytes."); + } + + return skip + avail; + } + else + { + int skip = (int)Math.min(n, available()); + bufOff += skip; + + return skip; + } } public int available() @@ -258,12 +331,50 @@ public class CipherInputStream return maxBuf - bufOff; } + /** + * Ensure the cipher text buffer has space sufficient to accept an upcoming output. + * + * @param updateSize the size of the pending update. + * @param finalOutputtrue
iff this the cipher is to be finalised. + */ + private void ensureCapacity(int updateSize, boolean finalOutput) + { + int bufLen = updateSize; + if (finalOutput) + { + if (bufferedBlockCipher != null) + { + bufLen = bufferedBlockCipher.getOutputSize(updateSize); + } + else if (aeadBlockCipher != null) + { + bufLen = aeadBlockCipher.getOutputSize(updateSize); + } + } + else + { + if (bufferedBlockCipher != null) + { + bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize); + } + else if (aeadBlockCipher != null) + { + bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize); + } + } + + if ((buf == null) || (buf.length < bufLen)) + { + buf = new byte[bufLen]; + } + } + /** * Closes the underlying input stream and finalises the processing of the data by the cipher. * * @throws IOException if there was an error closing the input stream. * @throws InvalidCipherTextIOException if the data read from the stream was invalid ciphertext - * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails). + * (e.g. the cipher is an AEAD cipher and the ciphertext tag check fails). */ public void close() throws IOException @@ -282,19 +393,84 @@ public class CipherInputStream } } maxBuf = bufOff = 0; + markBufOff = 0; + markPosition = 0; + if (markBuf != null) + { + Arrays.fill(markBuf, (byte)0); + markBuf = null; + } + if (buf != null) + { + Arrays.fill(buf, (byte)0); + buf = null; + } + Arrays.fill(inBuf, (byte)0); } + /** + * Mark the current position. + *+ * This method only works if markSupported() returns true - which means the underlying stream supports marking, and the cipher passed + * in to this stream's constructor is a SkippingCipher (so capable of being reset to an arbitrary point easily). + *
+ * @param readlimit the maximum read ahead required before a reset() may be called. + */ public void mark(int readlimit) { + in.mark(readlimit); + if (skippingCipher != null) + { + markPosition = skippingCipher.getPosition(); + } + + if (buf != null) + { + markBuf = new byte[buf.length]; + System.arraycopy(buf, 0, markBuf, 0, buf.length); + } + + markBufOff = bufOff; } + /** + * Reset to the last marked position, if supported. + * + * @throws IOException if marking not supported by the cipher used, or the underlying stream. + */ public void reset() throws IOException { - } + if (skippingCipher == null) + { + throw new IOException("cipher must implement SkippingCipher to be used with reset()"); + } + in.reset(); + + skippingCipher.seekTo(markPosition); + + if (markBuf != null) + { + buf = markBuf; + } + + bufOff = markBufOff; + } + + /** + * Return true if mark(readlimit) is supported. This will be true if the underlying stream supports marking and the + * cipher used is a SkippingCipher, + * + * @return true if mark(readlimit) supported, false otherwise. + */ public boolean markSupported() { + if (skippingCipher != null) + { + return in.markSupported(); + } + return false; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java index 797e838be..e45962f3a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/CipherOutputStream.java @@ -14,7 +14,7 @@ import org.spongycastle.crypto.modes.AEADBlockCipher; * the written data with the cipher, and the output of the cipher is in turn written to the * underlying OutputStream. The cipher must be fully initialized before being used by a * CipherInputStream. - * + ** For example, if the cipher is initialized for encryption, the CipherOutputStream will encrypt the * data before writing the encrypted data to the underlying stream. */ @@ -86,7 +86,7 @@ public class CipherOutputStream /** * Writes
+ *b.length
bytes from the specified byte array * to this output stream. - ** The
- * + *write
method of *CipherOutputStream
calls thewrite
* method of three arguments with the three arguments @@ -118,7 +118,7 @@ public class CipherOutputStream int len) throws IOException { - ensureCapacity(len); + ensureCapacity(len, false); if (bufferedBlockCipher != null) { @@ -149,24 +149,35 @@ public class CipherOutputStream /** * Ensure the ciphertext buffer has space sufficient to accept an upcoming output. * - * @param outputSize the size of the pending update. + * @param updateSize the size of the pending update. + * @param finalOutputtrue
iff this the cipher is to be finalised. */ - private void ensureCapacity(int outputSize) + private void ensureCapacity(int updateSize, boolean finalOutput) { - // This overestimates buffer on updates for AEAD/padded, but keeps it simple. - int bufLen; - if (bufferedBlockCipher != null) + int bufLen = updateSize; + if (finalOutput) { - bufLen = bufferedBlockCipher.getOutputSize(outputSize); - } - else if (aeadBlockCipher != null) - { - bufLen = aeadBlockCipher.getOutputSize(outputSize); + if (bufferedBlockCipher != null) + { + bufLen = bufferedBlockCipher.getOutputSize(updateSize); + } + else if (aeadBlockCipher != null) + { + bufLen = aeadBlockCipher.getOutputSize(updateSize); + } } else { - bufLen = outputSize; + if (bufferedBlockCipher != null) + { + bufLen = bufferedBlockCipher.getUpdateOutputSize(updateSize); + } + else if (aeadBlockCipher != null) + { + bufLen = aeadBlockCipher.getUpdateOutputSize(updateSize); + } } + if ((buf == null) || (buf.length < bufLen)) { buf = new byte[bufLen]; @@ -177,8 +188,7 @@ public class CipherOutputStream * Flushes this output stream by forcing any buffered output bytes * that have already been processed by the encapsulated cipher object * to be written out. - ** Any bytes buffered by the encapsulated cipher * and waiting to be processed by it will not be written out. For example, * if the encapsulated cipher is a block cipher, and the total number of @@ -196,12 +206,12 @@ public class CipherOutputStream /** * Closes this output stream and releases any system resources * associated with this stream. - *
+ ** This method invokes the
+ *doFinal
method of the encapsulated * cipher object, which causes any bytes buffered by the encapsulated * cipher to be processed. The result is written out by calling the *flush
method of this output stream. - ** This method resets the encapsulated cipher object to its initial state * and calls the
+ *close
method of the underlying output * stream. @@ -213,7 +223,7 @@ public class CipherOutputStream public void close() throws IOException { - ensureCapacity(0); + ensureCapacity(0, true); IOException error = null; try { @@ -242,7 +252,7 @@ public class CipherOutputStream } catch (Exception e) { - error = new IOException("Error closing stream: " + e); + error = new CipherIOException("Error closing stream: ", e); } try diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java index 60f218347..fd488a976 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/io/InvalidCipherTextIOException.java @@ -8,21 +8,12 @@ import java.io.IOException; * expose invalid ciphertext errors. */ public class InvalidCipherTextIOException - extends IOException + extends CipherIOException { private static final long serialVersionUID = 1L; - private final Throwable cause; - public InvalidCipherTextIOException(String message, Throwable cause) { - super(message); - - this.cause = cause; - } - - public Throwable getCause() - { - return cause; + super(message, cause); } } \ No newline at end of file diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java index bfe8c1077..500ac3ed3 100755 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/ECIESKeyEncapsulation.java @@ -13,7 +13,10 @@ import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.KDFParameters; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; +import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; /** @@ -120,8 +123,10 @@ public class ECIESKeyEncapsulation // Compute the static-ephemeral key agreement BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r; + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + ECPoint[] ghTilde = new ECPoint[]{ - ecParams.getG().multiply(r), + basePointMultiplier.multiply(ecParams.getG(), r), ecPubKey.getQ().multiply(rPrime) }; @@ -138,18 +143,7 @@ public class ECIESKeyEncapsulation byte[] PEH = hTilde.getAffineXCoord().getEncoded(); // Initialise the KDF - byte[] kdfInput; - if (SingleHashMode) - { - kdfInput = new byte[C.length + PEH.length]; - System.arraycopy(C, 0, kdfInput, 0, C.length); - System.arraycopy(PEH, 0, kdfInput, C.length, PEH.length); - } - else - { - kdfInput = PEH; - } - + byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH; kdf.init(new KDFParameters(kdfInput, null)); // Generate the secret key @@ -221,17 +215,7 @@ public class ECIESKeyEncapsulation byte[] PEH = hTilde.getAffineXCoord().getEncoded(); // Initialise the KDF - byte[] kdfInput; - if (SingleHashMode) - { - kdfInput = new byte[C.length + PEH.length]; - System.arraycopy(C, 0, kdfInput, 0, C.length); - System.arraycopy(PEH, 0, kdfInput, C.length, PEH.length); - } - else - { - kdfInput = PEH; - } + byte[] kdfInput = SingleHashMode ? Arrays.concatenate(C, PEH) : PEH; kdf.init(new KDFParameters(kdfInput, null)); // Generate the secret key @@ -252,4 +236,9 @@ public class ECIESKeyEncapsulation { return decrypt(in, 0, in.length, keyLen); } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java index 5f9a7f519..7c3dba57c 100755 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/kems/RSAKeyEncapsulation.java @@ -38,7 +38,6 @@ public class RSAKeyEncapsulation this.rnd = rnd; } - /** * Initialise the RSA-KEM. * @@ -51,12 +50,9 @@ public class RSAKeyEncapsulation { throw new IllegalArgumentException("RSA key required"); } - else - { - this.key = (RSAKeyParameters)key; - } - } + this.key = (RSAKeyParameters)key; + } /** * Generate and encapsulate a random session key. @@ -79,25 +75,15 @@ public class RSAKeyEncapsulation // Generate the ephemeral random and encode it BigInteger r = BigIntegers.createRandomInRange(ZERO, n.subtract(ONE), rnd); - byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r); // Encrypt the random and encode it BigInteger c = r.modPow(e, n); byte[] C = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, c); System.arraycopy(C, 0, out, outOff, C.length); - - // Initialise the KDF - kdf.init(new KDFParameters(R, null)); - - // Generate the secret key - byte[] K = new byte[keyLen]; - kdf.generateBytes(K, 0, K.length); - - return new KeyParameter(K); + return generateKey(n, r, keyLen); } - /** * Generate and encapsulate a random session key. * @@ -110,7 +96,6 @@ public class RSAKeyEncapsulation return encrypt(out, 0, keyLen); } - /** * Decrypt an encapsulated session key. * @@ -138,16 +123,8 @@ public class RSAKeyEncapsulation // Decrypt the ephemeral random and encode it BigInteger r = c.modPow(d, n); - byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r); - // Initialise the KDF - kdf.init(new KDFParameters(R, null)); - - // Generate the secret key - byte[] K = new byte[keyLen]; - kdf.generateBytes(K, 0, K.length); - - return new KeyParameter(K); + return generateKey(n, r, keyLen); } /** @@ -161,4 +138,18 @@ public class RSAKeyEncapsulation { return decrypt(in, 0, in.length, keyLen); } + + protected KeyParameter generateKey(BigInteger n, BigInteger r, int keyLen) + { + byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r); + + // Initialise the KDF + kdf.init(new KDFParameters(R, null)); + + // Generate the secret key + byte[] K = new byte[keyLen]; + kdf.generateBytes(K, 0, K.length); + + return new KeyParameter(K); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMac.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMac.java index c1947d063..5bf473824 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMac.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMac.java @@ -58,14 +58,14 @@ public class CMac implements Mac /** * create a standard MAC based on a block cipher with the size of the * MAC been given in bits. - ** Note: the size of the MAC must be at least 24 bits (FIPS Publication 81), * or 16 bits if being used as a data authenticator (FIPS Publication 113), * and in general should be less than the size of the block cipher as it reduces * the chance of an exhaustive attack (see Handbook of Applied Cryptography). * * @param cipher the cipher to be used as the basis of the MAC generation. - * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and <= 128. + * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and <= 128. */ public CMac(BlockCipher cipher, int macSizeInBits) { @@ -133,24 +133,31 @@ public class CMac implements Mac public void init(CipherParameters params) { - if (params instanceof KeyParameter) - { - cipher.init(true, params); - - //initializes the L, Lu, Lu2 numbers - L = new byte[ZEROES.length]; - cipher.processBlock(ZEROES, 0, L, 0); - Lu = doubleLu(L); - Lu2 = doubleLu(Lu); - } else if (params != null) - { - // CMAC mode does not permit IV to underlying CBC mode - throw new IllegalArgumentException("CMac mode only permits key to be set."); - } + validate(params); + + cipher.init(true, params); + + //initializes the L, Lu, Lu2 numbers + L = new byte[ZEROES.length]; + cipher.processBlock(ZEROES, 0, L, 0); + Lu = doubleLu(L); + Lu2 = doubleLu(Lu); reset(); } + void validate(CipherParameters params) + { + if (params != null) + { + if (!(params instanceof KeyParameter)) + { + // CMAC mode does not permit IV to underlying CBC mode + throw new IllegalArgumentException("CMac mode only permits key to be set."); + } + } + } + public int getMacSize() { return macSize; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java new file mode 100644 index 000000000..f4894a6e5 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/CMacWithIV.java @@ -0,0 +1,27 @@ +package org.spongycastle.crypto.macs; + +import org.spongycastle.crypto.BlockCipher; +import org.spongycastle.crypto.CipherParameters; + +/** + * A non-NIST variant which allows passing of an IV to the underlying CBC cipher. + *
Note: there isn't really a good reason to use an IV here, use the regular CMac where possible.
+ */ +public class CMacWithIV + extends CMac +{ + public CMacWithIV(BlockCipher cipher) + { + super(cipher); + } + + public CMacWithIV(BlockCipher cipher, int macSizeInBits) + { + super(cipher, macSizeInBits); + } + + void validate(CipherParameters params) + { + // accept all + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/GMac.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/GMac.java index acaa819a4..fc2e29f55 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/GMac.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/GMac.java @@ -23,7 +23,7 @@ public class GMac implements Mac /** * Creates a GMAC based on the operation of a block cipher in GCM mode. - * + ** This will produce an authentication code the length of the block size of the cipher. * * @param cipher @@ -40,7 +40,8 @@ public class GMac implements Mac * Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode. * * @param macSizeBits - * the mac size to generate, in bits. Must be a multiple of 8 and >= 96 and <= 128. + * the mac size to generate, in bits. Must be a multiple of 8 and >= 32 and <= 128. + * Sizes less than 96 are not recommended, but are supported for specialized applications. * @param cipher * the cipher to be used in GCM mode to generate the MAC. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java index ca1558d82..a33acbb19 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/Poly1305.java @@ -7,7 +7,7 @@ import org.spongycastle.crypto.Mac; import org.spongycastle.crypto.generators.Poly1305KeyGenerator; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; /** * Poly1305 message authentication code, designed by D. J. Bernstein. @@ -52,6 +52,14 @@ public class Poly1305 /** Polynomial accumulator */ private int h0, h1, h2, h3, h4; + /** + * Constructs a Poly1305 MAC, where the key passed to init() will be used directly. + */ + public Poly1305() + { + this.cipher = null; + } + /** * Constructs a Poly1305 MAC, using a 128 bit block cipher. */ @@ -66,35 +74,48 @@ public class Poly1305 /** * Initialises the Poly1305 MAC. - * - * @param a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with - * a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}. + * + * @param params if used with a block cipher, then a {@link ParametersWithIV} containing a 128 bit + * nonce and a {@link KeyParameter} with a 256 bit key complying to the + * {@link Poly1305KeyGenerator Poly1305 key format}, otherwise just the + * {@link KeyParameter}. */ - public void init(final CipherParameters params) + public void init(CipherParameters params) throws IllegalArgumentException { - final byte[] nonce; - final byte[] key; - if ((params instanceof ParametersWithIV) && ((ParametersWithIV)params).getParameters() instanceof KeyParameter) + byte[] nonce = null; + + if (cipher != null) { - nonce = ((ParametersWithIV)params).getIV(); - key = ((KeyParameter)((ParametersWithIV)params).getParameters()).getKey(); - } - else - { - throw new IllegalArgumentException("Poly1305 requires a key and and IV."); + if (!(params instanceof ParametersWithIV)) + { + throw new IllegalArgumentException("Poly1305 requires an IV when used with a block cipher."); + } + + ParametersWithIV ivParams = (ParametersWithIV)params; + nonce = ivParams.getIV(); + params = ivParams.getParameters(); } - setKey(key, nonce); + if (!(params instanceof KeyParameter)) + { + throw new IllegalArgumentException("Poly1305 requires a key."); + } + + KeyParameter keyParams = (KeyParameter)params; + + setKey(keyParams.getKey(), nonce); + reset(); } private void setKey(final byte[] key, final byte[] nonce) { - if (nonce.length != BLOCK_SIZE) + if (cipher != null && (nonce == null || nonce.length != BLOCK_SIZE)) { throw new IllegalArgumentException("Poly1305 requires a 128 bit IV."); } + Poly1305KeyGenerator.checkKey(key); // Extract r portion of key @@ -115,22 +136,28 @@ public class Poly1305 s3 = r3 * 5; s4 = r4 * 5; - // Compute encrypted nonce - final byte[] cipherKey = new byte[BLOCK_SIZE]; - System.arraycopy(key, 0, cipherKey, 0, cipherKey.length); + final byte[] kBytes; + if (cipher == null) + { + kBytes = key; + } + else + { + // Compute encrypted nonce + kBytes = new byte[BLOCK_SIZE]; + cipher.init(true, new KeyParameter(key, 0, BLOCK_SIZE)); + cipher.processBlock(nonce, 0, kBytes, 0); + } - cipher.init(true, new KeyParameter(cipherKey)); - cipher.processBlock(nonce, 0, cipherKey, 0); - - k0 = Pack.littleEndianToInt(cipherKey, 0); - k1 = Pack.littleEndianToInt(cipherKey, 4); - k2 = Pack.littleEndianToInt(cipherKey, 8); - k3 = Pack.littleEndianToInt(cipherKey, 12); + k0 = Pack.littleEndianToInt(kBytes, 0); + k1 = Pack.littleEndianToInt(kBytes, 4); + k2 = Pack.littleEndianToInt(kBytes, 8); + k3 = Pack.littleEndianToInt(kBytes, 12); } public String getAlgorithmName() { - return "Poly1305-" + cipher.getAlgorithmName(); + return cipher == null ? "Poly1305" : "Poly1305-" + cipher.getAlgorithmName(); } public int getMacSize() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java index 140576471..3489d4c1c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SipHash.java @@ -4,13 +4,12 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.Mac; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.crypto.util.Pack; -import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; /** * Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe * Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf). - *
+ ** "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of * compression rounds and the number of finalization rounds. A compression round is identical to a * finalization round and this round function is called SipRound. Given a 128-bit key k and a @@ -19,14 +18,13 @@ import org.spongycastle.util.Arrays; public class SipHash implements Mac { - protected final int c, d; protected long k0, k1; - protected long v0, v1, v2, v3, v4; + protected long v0, v1, v2, v3; - protected byte[] buf = new byte[8]; - protected int bufPos = 0; + protected long m = 0; + protected int wordPos = 0; protected int wordCount = 0; /** @@ -34,7 +32,7 @@ public class SipHash */ public SipHash() { - // use of this confuses flow analyser on earlier JDKs. + // use of 'this' confuses the flow analyser on earlier JDKs. this.c = 2; this.d = 4; } @@ -84,12 +82,13 @@ public class SipHash public void update(byte input) throws IllegalStateException { + m >>>= 8; + m |= (input & 0xffL) << 56; - buf[bufPos] = input; - if (++bufPos == buf.length) + if (++wordPos == 8) { processMessageWord(); - bufPos = 0; + wordPos = 0; } } @@ -97,14 +96,41 @@ public class SipHash throws DataLengthException, IllegalStateException { - - for (int i = 0; i < length; ++i) + int i = 0, fullWords = length & ~7; + if (wordPos == 0) { - buf[bufPos] = input[offset + i]; - if (++bufPos == buf.length) + for (; i < fullWords; i += 8) { + m = Pack.littleEndianToLong(input, offset + i); processMessageWord(); - bufPos = 0; + } + for (; i < length; ++i) + { + m >>>= 8; + m |= (input[offset + i] & 0xffL) << 56; + } + wordPos = length - fullWords; + } + else + { + int bits = wordPos << 3; + for (; i < fullWords; i += 8) + { + long n = Pack.littleEndianToLong(input, offset + i); + m = (n << bits) | (m >>> -bits); + processMessageWord(); + m = n; + } + for (; i < length; ++i) + { + m >>>= 8; + m |= (input[offset + i] & 0xffL) << 56; + + if (++wordPos == 8) + { + processMessageWord(); + wordPos = 0; + } } } } @@ -112,12 +138,10 @@ public class SipHash public long doFinal() throws DataLengthException, IllegalStateException { - - buf[7] = (byte)(((wordCount << 3) + bufPos) & 0xff); - while (bufPos < 7) - { - buf[bufPos++] = 0; - } + // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0 + m >>>= ((7 - wordPos) << 3); + m >>>= 8; + m |= (((wordCount << 3) + wordPos) & 0xffL) << 56; processMessageWord(); @@ -135,7 +159,6 @@ public class SipHash public int doFinal(byte[] out, int outOff) throws DataLengthException, IllegalStateException { - long result = doFinal(); Pack.longToLittleEndian(result, out, outOff); return 8; @@ -143,22 +166,19 @@ public class SipHash public void reset() { - v0 = k0 ^ 0x736f6d6570736575L; v1 = k1 ^ 0x646f72616e646f6dL; v2 = k0 ^ 0x6c7967656e657261L; v3 = k1 ^ 0x7465646279746573L; - Arrays.fill(buf, (byte)0); - bufPos = 0; + m = 0; + wordPos = 0; wordCount = 0; } protected void processMessageWord() { - ++wordCount; - long m = Pack.littleEndianToLong(buf, 0); v3 ^= m; applySipRounds(c); v0 ^= m; @@ -166,27 +186,31 @@ public class SipHash protected void applySipRounds(int n) { + long r0 = v0, r1 = v1, r2 = v2, r3 = v3; + for (int r = 0; r < n; ++r) { - v0 += v1; - v2 += v3; - v1 = rotateLeft(v1, 13); - v3 = rotateLeft(v3, 16); - v1 ^= v0; - v3 ^= v2; - v0 = rotateLeft(v0, 32); - v2 += v1; - v0 += v3; - v1 = rotateLeft(v1, 17); - v3 = rotateLeft(v3, 21); - v1 ^= v2; - v3 ^= v0; - v2 = rotateLeft(v2, 32); + r0 += r1; + r2 += r3; + r1 = rotateLeft(r1, 13); + r3 = rotateLeft(r3, 16); + r1 ^= r0; + r3 ^= r2; + r0 = rotateLeft(r0, 32); + r2 += r1; + r0 += r3; + r1 = rotateLeft(r1, 17); + r3 = rotateLeft(r3, 21); + r1 ^= r2; + r3 ^= r0; + r2 = rotateLeft(r2, 32); } + + v0 = r0; v1 = r1; v2 = r2; v3 = r3; } protected static long rotateLeft(long x, int n) { - return (x << n) | (x >>> (64 - n)); + return (x << n) | (x >>> -n); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java index 4d2ec47fe..b7a72f864 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/macs/SkeinMac.java @@ -10,13 +10,12 @@ import org.spongycastle.crypto.params.SkeinParameters; /** * Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes, * based on the {@link ThreefishEngine Threefish} tweakable block cipher. - *
+ ** This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3 * competition in October 2010. - *
+ ** Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker. - *
* * @see SkeinEngine * @see SkeinParameters diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java index ab8233824..ef48098e3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/AEADBlockCipher.java @@ -7,6 +7,16 @@ import org.spongycastle.crypto.InvalidCipherTextException; /** * A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data. + *+ * Implementations of this interface may operate in a packet mode (where all input data is buffered and + * processed dugin the call to {@link #doFinal(byte[], int)}), or in a streaming mode (where output data is + * incrementally produced with each call to {@link #processByte(byte, byte[], int)} or + * {@link #processBytes(byte[], int, int, byte[], int)}. + *
+ * This is important to consider during decryption: in a streaming mode, unauthenticated plaintext data + * may be output prior to the call to {@link #doFinal(byte[], int)} that results in an authentication + * failure. The higher level protocol utilising this cipher must ensure the plaintext data is handled + * appropriately until the end of data is reached and the entire ciphertext is authenticated. * @see org.spongycastle.crypto.params.AEADParameters */ public interface AEADBlockCipher @@ -101,6 +111,11 @@ public interface AEADBlockCipher /** * return the size of the output buffer required for a processBytes * an input of len bytes. + *+ * The returned size may be dependent on the initialisation of this cipher + * and may not be accurate once subsequent input data is processed - this method + * should be invoked immediately prior to input data being processed. + *
* * @param len the length of the input. * @return the space required to accommodate a call to processBytes @@ -111,7 +126,12 @@ public interface AEADBlockCipher /** * return the size of the output buffer required for a processBytes plus a * doFinal with an input of len bytes. - * + *+ * The returned size may be dependent on the initialisation of this cipher + * and may not be accurate once subsequent input data is processed - this method + * should be invoked immediately prior to a call to final processing of input data + * and a call to {@link #doFinal(byte[], int)}. + *
* @param len the length of the input. * @return the space required to accommodate a call to processBytes and doFinal * with len bytes of input. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java index 289d611b5..0b713f63c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CCMBlockCipher.java @@ -7,6 +7,7 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.Mac; +import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.macs.CBCBlockCipherMac; import org.spongycastle.crypto.params.AEADParameters; import org.spongycastle.crypto.params.ParametersWithIV; @@ -42,7 +43,7 @@ public class CCMBlockCipher 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."); @@ -99,7 +100,7 @@ public class CCMBlockCipher { throw new IllegalArgumentException("nonce must have length from 7 to 13 octets"); } - + reset(); } @@ -130,6 +131,10 @@ public class CCMBlockCipher public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff) throws DataLengthException, IllegalStateException { + if (in.length < (inOff + inLen)) + { + throw new DataLengthException("Input buffer too short"); + } data.write(in, inOff, inLen); return 0; @@ -155,15 +160,15 @@ public class CCMBlockCipher /** * 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; } @@ -267,7 +272,7 @@ public class CCMBlockCipher outputLen = inLen + macSize; if (output.length < (outputLen + outOff)) { - throw new DataLengthException("Output buffer too short."); + throw new OutputLengthException("Output buffer too short."); } calculateMac(in, inOff, inLen, macBlock); @@ -300,7 +305,7 @@ public class CCMBlockCipher outputLen = inLen - macSize; if (output.length < (outputLen + outOff)) { - throw new DataLengthException("Output buffer too short."); + throw new OutputLengthException("Output buffer too short."); } System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize); @@ -350,18 +355,18 @@ public class CCMBlockCipher // 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) @@ -370,22 +375,22 @@ public class CCMBlockCipher 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 @@ -396,7 +401,7 @@ public class CCMBlockCipher cMac.update((byte)(textLength >> 16)); cMac.update((byte)(textLength >> 8)); cMac.update((byte)textLength); - + extra = 6; } @@ -418,7 +423,7 @@ public class CCMBlockCipher } } } - + // // add the text // diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java index c22e34876..52bf2cc9c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/CFBBlockCipher.java @@ -3,6 +3,7 @@ package org.spongycastle.crypto.modes; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; @@ -10,15 +11,17 @@ import org.spongycastle.util.Arrays; * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher. */ public class CFBBlockCipher - implements BlockCipher + extends StreamBlockCipher { private byte[] IV; private byte[] cfbV; private byte[] cfbOutV; + private byte[] inBuf; private int blockSize; private BlockCipher cipher = null; private boolean encrypting; + private int byteCount; /** * Basic constructor. @@ -31,22 +34,15 @@ public class CFBBlockCipher BlockCipher cipher, int bitBlockSize) { + super(cipher); + this.cipher = cipher; this.blockSize = bitBlockSize / 8; this.IV = new byte[cipher.getBlockSize()]; this.cfbV = new byte[cipher.getBlockSize()]; this.cfbOutV = new byte[cipher.getBlockSize()]; - } - - /** - * return the underlying block cipher that we are wrapping. - * - * @return the underlying block cipher that we are wrapping. - */ - public BlockCipher getUnderlyingCipher() - { - return cipher; + this.inBuf = new byte[blockSize]; } /** @@ -117,6 +113,54 @@ public class CFBBlockCipher return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8); } + protected byte calculateByte(byte in) + throws DataLengthException, IllegalStateException + { + return (encrypting) ? encryptByte(in) : decryptByte(in); + } + + private byte encryptByte(byte in) + { + if (byteCount == 0) + { + cipher.processBlock(cfbV, 0, cfbOutV, 0); + } + + byte rv = (byte)(cfbOutV[byteCount] ^ in); + inBuf[byteCount++] = rv; + + if (byteCount == blockSize) + { + byteCount = 0; + + System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); + System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize); + } + + return rv; + } + + private byte decryptByte(byte in) + { + if (byteCount == 0) + { + cipher.processBlock(cfbV, 0, cfbOutV, 0); + } + + inBuf[byteCount] = in; + byte rv = (byte)(cfbOutV[byteCount++] ^ in); + + if (byteCount == blockSize) + { + byteCount = 0; + + System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); + System.arraycopy(inBuf, 0, cfbV, cfbV.length - blockSize, blockSize); + } + + return rv; + } + /** * return the block size we are operating at. * @@ -147,7 +191,9 @@ public class CFBBlockCipher int outOff) throws DataLengthException, IllegalStateException { - return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); + processBytes(in, inOff, blockSize, out, outOff); + + return blockSize; } /** @@ -169,31 +215,7 @@ public class CFBBlockCipher int outOff) throws DataLengthException, IllegalStateException { - if ((inOff + blockSize) > in.length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + blockSize) > out.length) - { - throw new DataLengthException("output buffer too short"); - } - - cipher.processBlock(cfbV, 0, cfbOutV, 0); - - // - // XOR the cfbV with the plaintext producing the ciphertext - // - for (int i = 0; i < blockSize; i++) - { - out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]); - } - - // - // change over the input block. - // - System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); - System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize); + processBytes(in, inOff, blockSize, out, outOff); return blockSize; } @@ -217,31 +239,7 @@ public class CFBBlockCipher int outOff) throws DataLengthException, IllegalStateException { - if ((inOff + blockSize) > in.length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + blockSize) > out.length) - { - throw new DataLengthException("output buffer too short"); - } - - cipher.processBlock(cfbV, 0, cfbOutV, 0); - - // - // change over the input block. - // - System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize); - System.arraycopy(in, inOff, cfbV, cfbV.length - blockSize, blockSize); - - // - // XOR the cfbV with the ciphertext producing the plaintext - // - for (int i = 0; i < blockSize; i++) - { - out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]); - } + processBytes(in, inOff, blockSize, out, outOff); return blockSize; } @@ -263,6 +261,8 @@ public class CFBBlockCipher public void reset() { System.arraycopy(IV, 0, cfbV, 0, IV.length); + Arrays.fill(inBuf, (byte)0); + byteCount = 0; cipher.reset(); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java index 93826a573..f997689bb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/EAXBlockCipher.java @@ -5,22 +5,23 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.Mac; +import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.macs.CMac; import org.spongycastle.crypto.params.AEADParameters; import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; /** - * A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and + * A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and * Efficiency - by M. Bellare, P. Rogaway, D. Wagner. - * + * * http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf - * - * EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block - * cipher to encrypt and authenticate data. It's on-line (the length of a + * + * EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block + * cipher to encrypt and authenticate data. It's on-line (the length of a * message isn't needed to begin processing it), has good performances, it's * simple and provably secure (provided the underlying block cipher is secure). - * + * * Of course, this implementations is NOT thread-safe. */ public class EAXBlockCipher @@ -43,7 +44,7 @@ public class EAXBlockCipher private byte[] nonceMac; private byte[] associatedTextMac; private byte[] macBlock; - + private int macSize; private byte[] bufBlock; private int bufOff; @@ -61,7 +62,6 @@ public class EAXBlockCipher blockSize = cipher.getBlockSize(); mac = new CMac(cipher); macBlock = new byte[blockSize]; - bufBlock = new byte[blockSize * 2]; associatedTextMac = new byte[mac.getMacSize()]; nonceMac = new byte[mac.getMacSize()]; this.cipher = new SICBlockCipher(cipher); @@ -113,6 +113,8 @@ public class EAXBlockCipher throw new IllegalArgumentException("invalid parameters passed to EAX"); } + bufBlock = new byte[forEncryption ? blockSize : (blockSize + macSize)]; + byte[] tag = new byte[blockSize]; // Key reuse implemented in CBC mode of underlying CMac @@ -123,9 +125,9 @@ public class EAXBlockCipher mac.update(nonce, 0, nonce.length); mac.doFinal(nonceMac, 0); - // Same BlockCipher underlies this and the mac, so reuse last key on cipher + // Same BlockCipher underlies this and the mac, so reuse last key on cipher cipher.init(true, new ParametersWithIV(null, nonceMac)); - + reset(); } @@ -218,6 +220,11 @@ public class EAXBlockCipher { initCipher(); + if (in.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } + int resultLen = 0; for (int i = 0; i != len; i++) @@ -240,12 +247,11 @@ public class EAXBlockCipher if (forEncryption) { - if (out.length < (outOff + extra)) + if (out.length < (outOff + extra + macSize)) { - throw new DataLengthException("Output buffer too short"); + throw new OutputLengthException("Output buffer too short"); } cipher.processBlock(bufBlock, 0, tmp, 0); - cipher.processBlock(bufBlock, blockSize, tmp, blockSize); System.arraycopy(tmp, 0, out, outOff, extra); @@ -261,6 +267,10 @@ public class EAXBlockCipher } else { + if (out.length < (outOff + extra - macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } if (extra < macSize) { throw new InvalidCipherTextException("data too short"); @@ -270,7 +280,6 @@ public class EAXBlockCipher mac.update(bufBlock, 0, extra - macSize); cipher.processBlock(bufBlock, 0, tmp, 0); - cipher.processBlock(bufBlock, blockSize, tmp, blockSize); System.arraycopy(tmp, 0, out, outOff, extra - macSize); } @@ -329,6 +338,10 @@ public class EAXBlockCipher if (bufOff == bufBlock.length) { + if (out.length < (outOff + blockSize)) + { + throw new OutputLengthException("Output buffer is too short"); + } // TODO Could move the processByte(s) calls to here // initCipher(); @@ -347,8 +360,12 @@ public class EAXBlockCipher size = cipher.processBlock(bufBlock, 0, out, outOff); } - bufOff = blockSize; - System.arraycopy(bufBlock, blockSize, bufBlock, 0, blockSize); + bufOff = 0; + if (!forEncryption) + { + System.arraycopy(bufBlock, blockSize, bufBlock, 0, macSize); + bufOff = macSize; + } return size; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java index 41e26fc17..545b6208f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCFBBlockCipher.java @@ -3,6 +3,7 @@ package org.spongycastle.crypto.modes; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.crypto.params.ParametersWithRandom; @@ -12,7 +13,7 @@ import org.spongycastle.crypto.params.ParametersWithSBox; * An implementation of the GOST CFB mode with CryptoPro key meshing as described in RFC 4357. */ public class GCFBBlockCipher - implements BlockCipher + extends StreamBlockCipher { private static final byte[] C = { @@ -30,6 +31,8 @@ public class GCFBBlockCipher public GCFBBlockCipher(BlockCipher engine) { + super(engine); + this.cfbEngine = new CFBBlockCipher(engine, engine.getBlockSize() * 8); } @@ -61,7 +64,8 @@ public class GCFBBlockCipher public String getAlgorithmName() { - return "G" + cfbEngine.getAlgorithmName(); + String name = cfbEngine.getAlgorithmName(); + return name.substring(0, name.indexOf('/') - 1) + "/G" + name.substring(name.indexOf('/') + 1); } public int getBlockSize() @@ -71,6 +75,13 @@ public class GCFBBlockCipher public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException + { + this.processBytes(in, inOff, cfbEngine.getBlockSize(), out, outOff); + + return cfbEngine.getBlockSize(); + } + + protected byte calculateByte(byte b) { if (counter > 0 && counter % 1024 == 0) { @@ -87,18 +98,18 @@ public class GCFBBlockCipher key = new KeyParameter(nextKey); - byte[] iv = new byte[8]; - base.init(true, key); - base.processBlock(cfbEngine.getCurrentIV(), 0, iv, 0); + byte[] iv = cfbEngine.getCurrentIV(); + + base.processBlock(iv, 0, iv, 0); cfbEngine.init(forEncryption, new ParametersWithIV(key, iv)); } - counter += cfbEngine.getBlockSize(); + counter++; - return cfbEngine.processBlock(in, inOff, out, outOff); + return cfbEngine.calculateByte(b); } public void reset() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java index 419bb0325..d45c586d1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GCMBlockCipher.java @@ -4,6 +4,7 @@ import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.modes.gcm.GCMExponentiator; import org.spongycastle.crypto.modes.gcm.GCMMultiplier; import org.spongycastle.crypto.modes.gcm.Tables1kGCMExponentiator; @@ -11,8 +12,8 @@ import org.spongycastle.crypto.modes.gcm.Tables8kGCMMultiplier; import org.spongycastle.crypto.params.AEADParameters; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; /** * Implements the Galois/Counter mode (GCM) detailed in @@ -23,7 +24,7 @@ public class GCMBlockCipher { private static final int BLOCK_SIZE = 16; - // not final due to a compiler bug + // not final due to a compiler bug private BlockCipher cipher; private GCMMultiplier multiplier; private GCMExponentiator exp; @@ -81,6 +82,10 @@ public class GCMBlockCipher return cipher.getAlgorithmName() + "/GCM"; } + /** + * NOTE: MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits. + * Sizes less than 96 are not recommended, but are supported for specialized applications. + */ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException { @@ -97,12 +102,12 @@ public class GCMBlockCipher initialAssociatedText = param.getAssociatedText(); int macSizeBits = param.getMacSize(); - if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0) + if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0) { throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits); } - macSize = macSizeBits / 8; + macSize = macSizeBits / 8; keyParam = param.getKey(); } else if (params instanceof ParametersWithIV) @@ -119,7 +124,7 @@ public class GCMBlockCipher throw new IllegalArgumentException("invalid parameters passed to GCM"); } - int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); + int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); this.bufBlock = new byte[bufLength]; if (nonce == null || nonce.length < 1) @@ -127,9 +132,7 @@ public class GCMBlockCipher throw new IllegalArgumentException("IV must be at least 1 byte"); } - // TODO This should be configurable by init parameters - // (but must be 16 if nonce length not 12) (BLOCK_SIZE?) -// this.tagLength = 16; + // TODO Restrict macSize to 16 if nonce length not 12? // Cipher always used in forward mode // if keyParam is null we're reusing the last key. @@ -144,6 +147,10 @@ public class GCMBlockCipher multiplier.init(H); exp = null; } + else if (this.H == null) + { + throw new IllegalArgumentException("Key must be specified in initial init"); + } this.J0 = new byte[BLOCK_SIZE]; @@ -188,7 +195,7 @@ public class GCMBlockCipher if (forEncryption) { - return totalData + macSize; + return totalData + macSize; } return totalData < macSize ? 0 : totalData - macSize; @@ -271,6 +278,10 @@ public class GCMBlockCipher public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { + if (in.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } int resultLen = 0; for (int i = 0; i < len; ++i) @@ -288,6 +299,10 @@ public class GCMBlockCipher private void outputBlock(byte[] output, int offset) { + if (output.length < (offset + BLOCK_SIZE)) + { + throw new OutputLengthException("Output buffer too short"); + } if (totalLength == 0) { initCipher(); @@ -324,6 +339,10 @@ public class GCMBlockCipher if (extra > 0) { + if (out.length < (outOff + extra)) + { + throw new OutputLengthException("Output buffer too short"); + } gCTRPartial(bufBlock, 0, extra, out, outOff); } @@ -376,7 +395,6 @@ public class GCMBlockCipher gHASHBlock(S, X); - // TODO Fix this if tagLength becomes configurable // T = MSBt(GCTRk(J0,S)) byte[] tag = new byte[BLOCK_SIZE]; cipher.processBlock(J0, 0, tag, 0); @@ -390,6 +408,10 @@ public class GCMBlockCipher if (forEncryption) { + if (out.length < (outOff + extra + macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } // Append T to the message System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize); resultLen += macSize; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java index 41fe48609..c982e230d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/GOFBBlockCipher.java @@ -3,17 +3,19 @@ package org.spongycastle.crypto.modes; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.params.ParametersWithIV; /** * implements the GOST 28147 OFB counter mode (GCTR). */ public class GOFBBlockCipher - implements BlockCipher + extends StreamBlockCipher { private byte[] IV; private byte[] ofbV; private byte[] ofbOutV; + private int byteCount; private final int blockSize; private final BlockCipher cipher; @@ -34,6 +36,8 @@ public class GOFBBlockCipher public GOFBBlockCipher( BlockCipher cipher) { + super(cipher); + this.cipher = cipher; this.blockSize = cipher.getBlockSize(); @@ -47,16 +51,6 @@ public class GOFBBlockCipher this.ofbOutV = new byte[cipher.getBlockSize()]; } - /** - * return the underlying block cipher that we are wrapping. - * - * @return the underlying block cipher that we are wrapping. - */ - public BlockCipher getUnderlyingCipher() - { - return cipher; - } - /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. @@ -127,7 +121,6 @@ public class GOFBBlockCipher return cipher.getAlgorithmName() + "/GCTR"; } - /** * return the block size we are operating at (in bytes). * @@ -158,44 +151,7 @@ public class GOFBBlockCipher int outOff) throws DataLengthException, IllegalStateException { - if ((inOff + blockSize) > in.length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + blockSize) > out.length) - { - throw new DataLengthException("output buffer too short"); - } - - if (firstStep) - { - firstStep = false; - cipher.processBlock(ofbV, 0, ofbOutV, 0); - N3 = bytesToint(ofbOutV, 0); - N4 = bytesToint(ofbOutV, 4); - } - N3 += C2; - N4 += C1; - intTobytes(N3, ofbV, 0); - intTobytes(N4, ofbV, 4); - - cipher.processBlock(ofbV, 0, ofbOutV, 0); - - // - // XOR the ofbV with the plaintext producing the cipher text (and - // the next input block). - // - for (int i = 0; i < blockSize; i++) - { - out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]); - } - - // - // change over the input block. - // - System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize); - System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize); + processBytes(in, inOff, blockSize, out, outOff); return blockSize; } @@ -210,7 +166,7 @@ public class GOFBBlockCipher N3 = 0; N4 = 0; System.arraycopy(IV, 0, ofbV, 0, IV.length); - + byteCount = 0; cipher.reset(); } @@ -234,4 +190,39 @@ public class GOFBBlockCipher out[outOff + 1] = (byte)(num >>> 8); out[outOff] = (byte)num; } + + protected byte calculateByte(byte b) + { + if (byteCount == 0) + { + if (firstStep) + { + firstStep = false; + cipher.processBlock(ofbV, 0, ofbOutV, 0); + N3 = bytesToint(ofbOutV, 0); + N4 = bytesToint(ofbOutV, 4); + } + N3 += C2; + N4 += C1; + intTobytes(N3, ofbV, 0); + intTobytes(N4, ofbV, 4); + + cipher.processBlock(ofbV, 0, ofbOutV, 0); + } + + byte rv = (byte)(ofbOutV[byteCount++] ^ b); + + if (byteCount == blockSize) + { + byteCount = 0; + + // + // change over the input block. + // + System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize); + System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize); + } + + return rv; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java index c0a4fcf0f..eb348eab6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OCBBlockCipher.java @@ -6,29 +6,28 @@ import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.crypto.params.AEADParameters; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; /** - * An implementation of the "work in progress" Internet-Draft The OCB Authenticated-Encryption - * Algorithm, licensed per: - * + * An implementation of RFC 7253 on The OCB + * Authenticated-Encryption Algorithm, licensed per: + **
License for * Open-Source Software Implementations of OCB (Jan 9, 2013) — “License 1”*/ public class OCBBlockCipher implements AEADBlockCipher { - private static final int BLOCK_SIZE = 16; private BlockCipher hashCipher; @@ -51,7 +50,9 @@ public class OCBBlockCipher /* * NONCE-DEPENDENT */ - private byte[] OffsetMAIN_0; + private byte[] KtopInput = null; + private byte[] Stretch = new byte[24]; + private byte[] OffsetMAIN_0 = new byte[16]; /* * PER-ENCRYPTION/DECRYPTION @@ -61,7 +62,7 @@ public class OCBBlockCipher private long hashBlockCount, mainBlockCount; private byte[] OffsetHASH; private byte[] Sum; - private byte[] OffsetMAIN; + private byte[] OffsetMAIN = new byte[16]; private byte[] Checksum; // NOTE: The MAC value is preserved after doFinal @@ -111,6 +112,7 @@ public class OCBBlockCipher public void init(boolean forEncryption, CipherParameters parameters) throws IllegalArgumentException { + boolean oldForEncryption = this.forEncryption; this.forEncryption = forEncryption; this.macBlock = null; @@ -164,14 +166,17 @@ public class OCBBlockCipher * KEY-DEPENDENT INITIALISATION */ - if (keyParameter == null) + if (keyParameter != null) { - // TODO If 'keyParameter' is null we're re-using the last key. + // hashCipher always used in forward mode + hashCipher.init(true, keyParameter); + mainCipher.init(forEncryption, keyParameter); + KtopInput = null; + } + else if (oldForEncryption != forEncryption) + { + throw new IllegalArgumentException("cannot change encrypting state without providing key."); } - - // hashCipher always used in forward mode - hashCipher.init(true, keyParameter); - mainCipher.init(forEncryption, keyParameter); this.L_Asterisk = new byte[16]; hashCipher.processBlock(L_Asterisk, 0, L_Asterisk, 0); @@ -185,25 +190,8 @@ public class OCBBlockCipher * NONCE-DEPENDENT AND PER-ENCRYPTION/DECRYPTION INITIALISATION */ - byte[] nonce = new byte[16]; - System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length); - nonce[0] = (byte)(macSize << 4); - nonce[15 - N.length] |= 1; + int bottom = processNonce(N); - int bottom = nonce[15] & 0x3F; - - byte[] Ktop = new byte[16]; - nonce[15] &= 0xC0; - hashCipher.processBlock(nonce, 0, Ktop, 0); - - byte[] Stretch = new byte[24]; - System.arraycopy(Ktop, 0, Stretch, 0, 16); - for (int i = 0; i < 8; ++i) - { - Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]); - } - - this.OffsetMAIN_0 = new byte[16]; int bits = bottom % 8, bytes = bottom / 8; if (bits == 0) { @@ -227,7 +215,7 @@ public class OCBBlockCipher this.OffsetHASH = new byte[16]; this.Sum = new byte[16]; - this.OffsetMAIN = Arrays.clone(this.OffsetMAIN_0); + System.arraycopy(this.OffsetMAIN_0, 0, this.OffsetMAIN, 0, 16); this.Checksum = new byte[16]; if (initialAssociatedText != null) @@ -236,6 +224,34 @@ public class OCBBlockCipher } } + protected int processNonce(byte[] N) + { + byte[] nonce = new byte[16]; + System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length); + nonce[0] = (byte)(macSize << 4); + nonce[15 - N.length] |= 1; + + int bottom = nonce[15] & 0x3F; + nonce[15] &= 0xC0; + + /* + * When used with incrementing nonces, the cipher is only applied once every 64 inits. + */ + if (KtopInput == null || !Arrays.areEqual(nonce, KtopInput)) + { + byte[] Ktop = new byte[16]; + KtopInput = nonce; + hashCipher.processBlock(KtopInput, 0, Ktop, 0); + System.arraycopy(Ktop, 0, Stretch, 0, 16); + for (int i = 0; i < 8; ++i) + { + Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]); + } + } + + return bottom; + } + public byte[] getMac() { return Arrays.clone(macBlock); @@ -301,6 +317,10 @@ public class OCBBlockCipher public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff) throws DataLengthException { + if (input.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } int resultLen = 0; for (int i = 0; i < len; ++i) @@ -362,6 +382,10 @@ public class OCBBlockCipher xor(mainBlock, Pad); + if (output.length < (outOff + mainBlockPos)) + { + throw new OutputLengthException("Output buffer too short"); + } System.arraycopy(mainBlock, 0, output, outOff, mainBlockPos); if (!forEncryption) @@ -389,6 +413,10 @@ public class OCBBlockCipher if (forEncryption) { + if (output.length < (outOff + resultLen + macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } // Append tag to the message System.arraycopy(macBlock, 0, output, outOff + resultLen, macSize); resultLen += macSize; @@ -440,6 +468,11 @@ public class OCBBlockCipher protected void processMainBlock(byte[] output, int outOff) { + if (output.length < (outOff + BLOCK_SIZE)) + { + throw new OutputLengthException("Output buffer too short"); + } + /* * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks */ @@ -537,7 +570,7 @@ public class OCBBlockCipher while ((x & 1L) == 0L) { ++n; - x >>= 1; + x >>>= 1; } return n; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java index 3756c7f13..629d2c1e7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/OFBBlockCipher.java @@ -3,14 +3,16 @@ package org.spongycastle.crypto.modes; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.params.ParametersWithIV; /** * implements a Output-FeedBack (OFB) mode on top of a simple cipher. */ public class OFBBlockCipher - implements BlockCipher + extends StreamBlockCipher { + private int byteCount; private byte[] IV; private byte[] ofbV; private byte[] ofbOutV; @@ -29,6 +31,8 @@ public class OFBBlockCipher BlockCipher cipher, int blockSize) { + super(cipher); + this.cipher = cipher; this.blockSize = blockSize / 8; @@ -37,16 +41,6 @@ public class OFBBlockCipher this.ofbOutV = new byte[cipher.getBlockSize()]; } - /** - * return the underlying block cipher that we are wrapping. - * - * @return the underlying block cipher that we are wrapping. - */ - public BlockCipher getUnderlyingCipher() - { - return cipher; - } - /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. @@ -113,7 +107,7 @@ public class OFBBlockCipher return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8); } - + /** * return the block size we are operating at (in bytes). * @@ -144,32 +138,7 @@ public class OFBBlockCipher int outOff) throws DataLengthException, IllegalStateException { - if ((inOff + blockSize) > in.length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + blockSize) > out.length) - { - throw new DataLengthException("output buffer too short"); - } - - cipher.processBlock(ofbV, 0, ofbOutV, 0); - - // - // XOR the ofbV with the plaintext producing the cipher text (and - // the next input block). - // - for (int i = 0; i < blockSize; i++) - { - out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]); - } - - // - // change over the input block. - // - System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize); - System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize); + processBytes(in, inOff, blockSize, out, outOff); return blockSize; } @@ -181,7 +150,29 @@ public class OFBBlockCipher public void reset() { System.arraycopy(IV, 0, ofbV, 0, IV.length); + byteCount = 0; cipher.reset(); } + + protected byte calculateByte(byte in) + throws DataLengthException, IllegalStateException + { + if (byteCount == 0) + { + cipher.processBlock(ofbV, 0, ofbOutV, 0); + } + + byte rv = (byte)(ofbOutV[byteCount++] ^ in); + + if (byteCount == blockSize) + { + byteCount = 0; + + System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize); + System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize); + } + + return rv; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java index f228baf35..8f6f98435 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java @@ -3,14 +3,18 @@ package org.spongycastle.crypto.modes; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.SkippingStreamCipher; +import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.util.Pack; /** * Implements the Segmented Integer Counter (SIC) mode on top of a simple * block cipher. This mode is also known as CTR mode. */ public class SICBlockCipher - implements BlockCipher + extends StreamBlockCipher + implements SkippingStreamCipher { private final BlockCipher cipher; private final int blockSize; @@ -18,7 +22,7 @@ public class SICBlockCipher private byte[] IV; private byte[] counter; private byte[] counterOut; - + private int byteCount; /** * Basic constructor. @@ -27,25 +31,16 @@ public class SICBlockCipher */ public SICBlockCipher(BlockCipher c) { + super(c); + this.cipher = c; this.blockSize = cipher.getBlockSize(); this.IV = new byte[blockSize]; this.counter = new byte[blockSize]; this.counterOut = new byte[blockSize]; + this.byteCount = 0; } - - /** - * 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, //ignored by this CTR mode CipherParameters params) @@ -53,17 +48,17 @@ public class SICBlockCipher { if (params instanceof ParametersWithIV) { - ParametersWithIV ivParam = (ParametersWithIV)params; - byte[] iv = ivParam.getIV(); - System.arraycopy(iv, 0, IV, 0, IV.length); + ParametersWithIV ivParam = (ParametersWithIV)params; + byte[] iv = ivParam.getIV(); + System.arraycopy(iv, 0, IV, 0, IV.length); - reset(); + // if null it's an IV changed only. + if (ivParam.getParameters() != null) + { + cipher.init(true, ivParam.getParameters()); + } - // if null it's an IV changed only. - if (ivParam.getParameters() != null) - { - cipher.init(true, ivParam.getParameters()); - } + reset(); } else { @@ -81,33 +76,150 @@ public class SICBlockCipher return cipher.getBlockSize(); } - public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { - cipher.processBlock(counter, 0, counterOut, 0); + processBytes(in, inOff, blockSize, out, outOff); - // - // XOR the counterOut with the plaintext producing the cipher text - // - for (int i = 0; i < counterOut.length; i++) + return blockSize; + } + + protected byte calculateByte(byte in) + throws DataLengthException, IllegalStateException + { + if (byteCount == 0) { - out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]); + cipher.processBlock(counter, 0, counterOut, 0); + + return (byte)(counterOut[byteCount++] ^ in); } + byte rv = (byte)(counterOut[byteCount++] ^ in); + + if (byteCount == counter.length) + { + byteCount = 0; + + incrementCounter(); + } + + return rv; + } + + private void incrementCounter() + { // increment counter by 1. for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--) { ; // do nothing - pre-increment and test for 0 in counter does the job. } - - return counter.length; } + private void decrementCounter() + { + if (counter[0] == 0) + { + boolean nonZero = false; + + for (int i = counter.length - 1; i > 0; i--) + { + if (counter[i] != 0) + { + nonZero = true; + } + } + + if (!nonZero) + { + throw new IllegalStateException("attempt to reduce counter past zero."); + } + } + + // decrement counter by 1. + for (int i = counter.length - 1; i >= 0 && --counter[i] == -1; i--) + { + ; + } + } + + private void adjustCounter(long n) + { + if (n >= 0) + { + long numBlocks = (n + byteCount) / blockSize; + + for (long i = 0; i != numBlocks; i++) + { + incrementCounter(); + } + + byteCount = (int)((n + byteCount) - (blockSize * numBlocks)); + } + else + { + long numBlocks = (-n - byteCount) / blockSize; + + for (long i = 0; i != numBlocks; i++) + { + decrementCounter(); + } + + int gap = (int)(byteCount + n + (blockSize * numBlocks)); + + if (gap >= 0) + { + byteCount = 0; + } + else + { + decrementCounter(); + byteCount = blockSize + gap; + } + } + } public void reset() { System.arraycopy(IV, 0, counter, 0, counter.length); cipher.reset(); + this.byteCount = 0; + } + + public long skip(long numberOfBytes) + { + adjustCounter(numberOfBytes); + + cipher.processBlock(counter, 0, counterOut, 0); + + return numberOfBytes; + } + + public long seekTo(long position) + { + reset(); + + return skip(position); + } + + public long getPosition() + { + byte[] res = new byte[IV.length]; + + System.arraycopy(counter, 0, res, 0, res.length); + + for (int i = res.length - 1; i >= 1; i--) + { + int v = (res[i] - IV[i]); + + if (v < 0) + { + res[i - 1]--; + v += 256; + } + + res[i] = (byte)v; + } + + return Pack.bigEndianToLong(res, res.length - 8) * blockSize + byteCount; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java index ffb21997c..77be4b878 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/GCMUtil.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.modes.gcm; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; abstract class GCMUtil { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java index 3c26ea9a7..352ffc58a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.modes.gcm; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; public class Tables64kGCMMultiplier implements GCMMultiplier { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java index 220370c05..65e0389a0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.modes.gcm; -import org.spongycastle.crypto.util.Pack; import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; public class Tables8kGCMMultiplier implements GCMMultiplier { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java index 7165a82a8..c479a0629 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/paddings/PaddedBufferedBlockCipher.java @@ -125,7 +125,7 @@ public class PaddedBufferedBlockCipher if (leftOver == 0) { - return total - buf.length; + return Math.max(0, total - buf.length); } return total - leftOver; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java new file mode 100644 index 000000000..38976d2c6 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyGenerationParameters.java @@ -0,0 +1,24 @@ +package org.spongycastle.crypto.params; + +import java.security.SecureRandom; + +import org.spongycastle.crypto.KeyGenerationParameters; + +public class CramerShoupKeyGenerationParameters extends KeyGenerationParameters { + + private CramerShoupParameters params; + + public CramerShoupKeyGenerationParameters(SecureRandom random, CramerShoupParameters params) { + super(random, getStrength(params)); + + this.params = params; + } + + public CramerShoupParameters getParameters() { + return params; + } + + static int getStrength(CramerShoupParameters params) { + return params.getP().bitLength(); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java new file mode 100644 index 000000000..5bacd588e --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupKeyParameters.java @@ -0,0 +1,40 @@ +package org.spongycastle.crypto.params; + +public class CramerShoupKeyParameters extends AsymmetricKeyParameter { + + private CramerShoupParameters params; + + protected CramerShoupKeyParameters(boolean isPrivate, CramerShoupParameters params) { + super(isPrivate); + + this.params = params; + } + + public CramerShoupParameters getParameters() { + return params; + } + + public boolean equals(Object obj) { + if (!(obj instanceof CramerShoupKeyParameters)) { + return false; + } + + CramerShoupKeyParameters csKey = (CramerShoupKeyParameters) obj; + + if (params == null) { + return csKey.getParameters() == null; + } else { + return params.equals(csKey.getParameters()); + } + } + + public int hashCode() { + int code = isPrivate() ? 0 : 1; + + if (params != null) { + code ^= params.hashCode(); + } + + return code; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java new file mode 100644 index 000000000..d1504bab4 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupParameters.java @@ -0,0 +1,53 @@ +package org.spongycastle.crypto.params; + +import java.math.BigInteger; + +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.Digest; + +public class CramerShoupParameters implements CipherParameters { + + private BigInteger p; // prime order of G + private BigInteger g1, g2; // generate G + + private Digest H; // hash function + + public CramerShoupParameters(BigInteger p, BigInteger g1, BigInteger g2, Digest H) { + this.p = p; + this.g1 = g1; + this.g2 = g2; + this.H = H; + } + + public boolean equals(Object obj) { + if (!(obj instanceof DSAParameters)) { + return false; + } + + CramerShoupParameters pm = (CramerShoupParameters) obj; + + return (pm.getP().equals(p) && pm.getG1().equals(g1) && pm.getG2().equals(g2)); + } + + public int hashCode() { + return getP().hashCode() ^ getG1().hashCode() ^ getG2().hashCode(); + } + + public BigInteger getG1() { + return g1; + } + + public BigInteger getG2() { + return g2; + } + + public BigInteger getP() { + return p; + } + + public Digest getH() { + H.reset(); + return H; + } + +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java new file mode 100644 index 000000000..6aae8be20 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPrivateKeyParameters.java @@ -0,0 +1,61 @@ +package org.spongycastle.crypto.params; + +import java.math.BigInteger; + +public class CramerShoupPrivateKeyParameters extends CramerShoupKeyParameters { + + private BigInteger x1, x2, y1, y2, z; // Z_p + private CramerShoupPublicKeyParameters pk; // public key + + public CramerShoupPrivateKeyParameters(CramerShoupParameters params, BigInteger x1, BigInteger x2, BigInteger y1, BigInteger y2, BigInteger z) { + super(true, params); + + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + this.z = z; + } + + public BigInteger getX1() { + return x1; + } + + public BigInteger getX2() { + return x2; + } + + public BigInteger getY1() { + return y1; + } + + public BigInteger getY2() { + return y2; + } + + public BigInteger getZ() { + return z; + } + + public void setPk(CramerShoupPublicKeyParameters pk) { + this.pk = pk; + } + + public CramerShoupPublicKeyParameters getPk() { + return pk; + } + + public int hashCode() { + return x1.hashCode() ^ x2.hashCode() ^ y1.hashCode() ^ y2.hashCode() ^ z.hashCode() ^ super.hashCode(); + } + + public boolean equals(Object obj) { + if (!(obj instanceof CramerShoupPrivateKeyParameters)) { + return false; + } + + CramerShoupPrivateKeyParameters other = (CramerShoupPrivateKeyParameters) obj; + + return other.getX1().equals(this.x1) && other.getX2().equals(this.x2) && other.getY1().equals(this.y1) && other.getY2().equals(this.y2) && other.getZ().equals(this.z) && super.equals(obj); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java new file mode 100644 index 000000000..20752bf66 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/CramerShoupPublicKeyParameters.java @@ -0,0 +1,42 @@ +package org.spongycastle.crypto.params; + +import java.math.BigInteger; + +public class CramerShoupPublicKeyParameters extends CramerShoupKeyParameters { + + private BigInteger c, d, h; // public key group elements + + public CramerShoupPublicKeyParameters(CramerShoupParameters params, BigInteger c, BigInteger d, BigInteger h) { + super(false, params); + + this.c = c; + this.d = d; + this.h = h; + } + + public BigInteger getC() { + return c; + } + + public BigInteger getD() { + return d; + } + + public BigInteger getH() { + return h; + } + + public int hashCode() { + return c.hashCode() ^ d.hashCode() ^ h.hashCode() ^ super.hashCode(); + } + + public boolean equals(Object obj) { + if (!(obj instanceof CramerShoupPublicKeyParameters)) { + return false; + } + + CramerShoupPublicKeyParameters other = (CramerShoupPublicKeyParameters) obj; + + return other.getC().equals(c) && other.getD().equals(d) && other.getH().equals(h) && super.equals(obj); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java new file mode 100644 index 000000000..b6bb23c18 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/ECNamedDomainParameters.java @@ -0,0 +1,35 @@ +package org.spongycastle.crypto.params; + +import java.math.BigInteger; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; + +public class ECNamedDomainParameters + extends ECDomainParameters +{ + private ASN1ObjectIdentifier name; + + public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n) + { + this(name, curve, G, n, null, null); + } + + public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h) + { + this(name, curve, G, n, h, null); + } + + public ECNamedDomainParameters(ASN1ObjectIdentifier name, ECCurve curve, ECPoint G, BigInteger n, BigInteger h, byte[] seed) + { + super(curve, G, n, h, seed); + + this.name = name; + } + + public ASN1ObjectIdentifier getName() + { + return name; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java index b8930ce17..02ee9142d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/KDFCounterParameters.java @@ -3,15 +3,63 @@ package org.spongycastle.crypto.params; import org.spongycastle.crypto.DerivationParameters; import org.spongycastle.util.Arrays; +/** + * This KDF has been defined by the publicly available NIST SP 800-108 specification. + * NIST SP800-108 allows for alternative orderings of the input fields, meaning that the input can be formated in multiple ways. + * There are 3 supported formats: - Below [i]_2 is a counter of r-bits length concatenated to the fixedInputData. + *
* Under this license, you are authorized to make, use, and distribute open-source software * implementations of OCB. This license terminates for you if you sue someone over their open-source * software implementation of OCB claiming that you have a patent covering their implementation. - * + ** This is a non-binding summary of a legal document (the link above). The parameters of the license * are specified in the license document and that document is controlling.
+ *
+ *- 1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning of the fixedInputData (The default implementation has this format)
+ *- 2: K(i) := PRF( KI, Label || 0x00 || Context || [L]_2 || [i]_2 ) with the counter at the very end of the fixedInputData
+ *- 3a: K(i) := PRF( KI, Label || 0x00 || [i]_2 || Context || [L]_2 ) OR:
+ *- 3b: K(i) := PRF( KI, Label || 0x00 || [i]_2 || [L]_2 || Context ) OR:
+ *- 3c: K(i) := PRF( KI, Label || [i]_2 || 0x00 || Context || [L]_2 ) etc... with the counter somewhere in the 'middle' of the fixedInputData.
+ *+ * This function must be called with the following KDFCounterParameters(): + * - KI
+ * Resulting function calls assuming an 8 bit counter. + *
+ * - The part of the fixedInputData that comes BEFORE the counter OR null
+ * - the part of the fixedInputData that comes AFTER the counter OR null
+ * - the length of the counter in bits (not bytes)
+ *+ *
+ */ public final class KDFCounterParameters implements DerivationParameters { - private final byte[] ki; - private final byte[] fixedInputData; - private final int r; + private byte[] ki; + private byte[] fixedInputDataCounterPrefix; + private byte[] fixedInputDataCounterSuffix; + private int r; - public KDFCounterParameters(byte[] ki, byte[] fixedInputData, int r) + /** + * Base constructor - suffix fixed input data only. + * + * @param ki the KDF seed + * @param fixedInputDataCounterSuffix fixed input data to follow counter. + * @param r length of the counter in bits. + */ + public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterSuffix, int r) + { + this(ki, null, fixedInputDataCounterSuffix, r); + } + + /** + * Base constructor - prefix and suffix fixed input data. + * + * @param ki the KDF seed + * @param fixedInputDataCounterPrefix fixed input data to precede counter + * @param fixedInputDataCounterSuffix fixed input data to follow counter. + * @param r length of the counter in bits. + */ + public KDFCounterParameters(byte[] ki, byte[] fixedInputDataCounterPrefix, byte[] fixedInputDataCounterSuffix, int r) { if (ki == null) { @@ -19,13 +67,22 @@ public final class KDFCounterParameters } this.ki = Arrays.clone(ki); - if (fixedInputData == null) + if (fixedInputDataCounterPrefix == null) { - this.fixedInputData = new byte[0]; + this.fixedInputDataCounterPrefix = new byte[0]; } else { - this.fixedInputData = Arrays.clone(fixedInputData); + this.fixedInputDataCounterPrefix = Arrays.clone(fixedInputDataCounterPrefix); + } + + if (fixedInputDataCounterSuffix == null) + { + this.fixedInputDataCounterSuffix = new byte[0]; + } + else + { + this.fixedInputDataCounterSuffix = Arrays.clone(fixedInputDataCounterSuffix); } if (r != 8 && r != 16 && r != 24 && r != 32) @@ -34,7 +91,7 @@ public final class KDFCounterParameters } this.r = r; } - + public byte[] getKI() { return ki; @@ -42,7 +99,18 @@ public final class KDFCounterParameters public byte[] getFixedInputData() { - return Arrays.clone(fixedInputData); + //Retained for backwards compatibility + return Arrays.clone(fixedInputDataCounterSuffix); + } + + public byte[] getFixedInputDataCounterPrefix() + { + return Arrays.clone(fixedInputDataCounterPrefix); + } + + public byte[] getFixedInputDataCounterSuffix() + { + return Arrays.clone(fixedInputDataCounterSuffix); } public int getR() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java index f706409e5..0f4fc0ef7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/params/SkeinParameters.java @@ -8,6 +8,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Locale; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.digests.SkeinDigest; @@ -17,7 +18,7 @@ import org.spongycastle.util.Integers; /** * Parameters for the Skein hash function - a series of byte[] strings identified by integer tags. - * + *- 1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8);
+ *- 2. KDFCounterParameters(ki, "Label || 0x00 || Context || [L]_2]", null, 8);
+ *- 3a. KDFCounterParameters(ki, "Label || 0x00", "Context || [L]_2]", 8);
+ *- 3b. KDFCounterParameters(ki, "Label || 0x00", "[L]_2] || Context", 8);
+ *- 3c. KDFCounterParameters(ki, "Label", "0x00 || Context || [L]_2]", 8);
+ ** Parameterised Skein can be used for: *
*
- MAC generation, by providing a {@link SkeinParameters.Builder#setKey(byte[]) key}.
@@ -179,9 +180,9 @@ public class SkeinParameters * Sets a parameters to apply to the Skein hash function.
* Parameter types must be in the range 0,5..62, and cannot use the value {@value * SkeinParameters#PARAM_TYPE_MESSAGE} (reserved for message body). - * - * Parameters with type < {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before - * the message content, parameters with type > {@value SkeinParameters#PARAM_TYPE_MESSAGE} + *+ * Parameters with type < {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before + * the message content, parameters with type > {@value SkeinParameters#PARAM_TYPE_MESSAGE} * are processed after the message and prior to output. * * @param type the type of the parameter, in the range 5..62. @@ -227,14 +228,14 @@ public class SkeinParameters /** * Implements the recommended personalisation format for Skein defined in Section 4.11 of * the Skein 1.3 specification. - *
+ ** The format is
YYYYMMDD email@address distinguisher
, encoded to a byte * sequence using UTF-8 encoding. * * @param date the date the personalised application of the Skein was defined. * @param emailAddress the email address of the creation of the personalised application. * @param distinguisher an arbitrary personalisation string distinguishing the application. - * @return + * @return the current builder. */ public Builder setPersonalisation(Date date, String emailAddress, String distinguisher) { @@ -257,6 +258,41 @@ public class SkeinParameters } } + /** + * Implements the recommended personalisation format for Skein defined in Section 4.11 of + * the Skein 1.3 specification. You may need to use this method if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible implementations. + *+ * The format is
YYYYMMDD email@address distinguisher
, encoded to a byte + * sequence using UTF-8 encoding. + * + * @param date the date the personalised application of the Skein was defined. + * @param dateLocale locale to be used for date interpretation. + * @param emailAddress the email address of the creation of the personalised application. + * @param distinguisher an arbitrary personalisation string distinguishing the application. + * @return the current builder. + */ + public Builder setPersonalisation(Date date, Locale dateLocale, String emailAddress, String distinguisher) + { + try + { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8"); + final DateFormat format = new SimpleDateFormat("YYYYMMDD", dateLocale); + out.write(format.format(date)); + out.write(" "); + out.write(emailAddress); + out.write(" "); + out.write(distinguisher); + out.close(); + return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray()); + } + catch (IOException e) + { + throw new IllegalStateException("Byte I/O failed: " + e); + } + } + /** * Sets the {@link SkeinParameters#PARAM_TYPE_KEY_IDENTIFIER} parameter. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java index dbb0d30e4..bae1bc394 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/VMPCRandomGenerator.java @@ -1,6 +1,6 @@ package org.spongycastle.crypto.prng; -import org.spongycastle.crypto.util.Pack; +import org.spongycastle.util.Pack; public class VMPCRandomGenerator implements RandomGenerator { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java index 5fbdf37e1..26316685d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/CTRSP800DRBG.java @@ -309,6 +309,16 @@ public class CTRSP800DRBG buf[offSet + 3] = ((byte)(value)); } + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int getBlockSize() + { + return _V.length * 8; + } + /** * Populate a passed in array with random data. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java index 04a8a5a00..251b319f3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECPoints.java @@ -19,7 +19,7 @@ public class DualECPoints ** max_outlen = largest multiple of 8 less than ((field size in bits) - (13 + log2(cofactor)) *- * + * * @param securityStrength maximum security strength to be associated with these parameters * @param p the P point. * @param q the Q point. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java index 13765bf2c..239ffe57c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/DualECSP800DRBG.java @@ -6,7 +6,9 @@ import org.spongycastle.asn1.nist.NISTNamedCurves; import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.prng.EntropySource; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; @@ -70,6 +72,7 @@ public class DualECSP800DRBG private ECPoint _Q; private byte[] _s; private int _sLength; + private ECMultiplier _fixedPointMultiplier = new FixedPointCombMultiplier(); /** * Construct a SP800-90A Dual EC DRBG. @@ -145,6 +148,16 @@ public class DualECSP800DRBG _reseedCounter = 0; } + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int getBlockSize() + { + return _outlen * 8; + } + /** * Populate a passed in array with random data. * @@ -199,7 +212,7 @@ public class DualECSP800DRBG //System.err.println("S: " + new String(Hex.encode(_s))); - byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray(); + byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray(); if (r.length > _outlen) { @@ -220,7 +233,7 @@ public class DualECSP800DRBG { s = getScalarMultipleXCoord(_P, s); - byte[] r = _Q.multiply(s).normalize().getAffineXCoord().toBigInteger().toByteArray(); + byte[] r = getScalarMultipleXCoord(_Q, s).toByteArray(); int required = output.length - outOffset; @@ -237,7 +250,7 @@ public class DualECSP800DRBG } // Need to preserve length of S as unsigned int. - _s = BigIntegers.asUnsignedByteArray(_sLength, _P.multiply(s).normalize().getAffineXCoord().toBigInteger()); + _s = BigIntegers.asUnsignedByteArray(_sLength, getScalarMultipleXCoord(_P, s)); return numberOfBits; } @@ -302,6 +315,6 @@ public class DualECSP800DRBG private BigInteger getScalarMultipleXCoord(ECPoint p, BigInteger s) { - return p.multiply(s).normalize().getAffineXCoord().toBigInteger(); + return _fixedPointMultiplier.multiply(p, s).normalize().getAffineXCoord().toBigInteger(); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java index ad93896cc..6d2d4247a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HMacSP800DRBG.java @@ -87,6 +87,16 @@ public class HMacSP800DRBG _hMac.doFinal(_V, 0); } + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each round of the DRBG. + */ + public int getBlockSize() + { + return _V.length * 8; + } + /** * Populate a passed in array with random data. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java index 822724942..134980468 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/HashSP800DRBG.java @@ -87,6 +87,16 @@ public class HashSP800DRBG _reseedCounter = 1; } + /** + * Return the block size (in bits) of the DRBG. + * + * @return the number of bits produced on each internal round of the DRBG. + */ + public int getBlockSize() + { + return _digest.getDigestSize() * 8; + } + /** * Populate a passed in array with random data. * @@ -226,12 +236,17 @@ public class HashSP800DRBG private byte[] hash(byte[] input) { - _digest.update(input, 0, input.length); byte[] hash = new byte[_digest.getDigestSize()]; - _digest.doFinal(hash, 0); + doHash(input, hash); return hash; } - + + private void doHash(byte[] input, byte[] output) + { + _digest.update(input, 0, input.length); + _digest.doFinal(output, 0); + } + // 1. m = [requested_number_of_bits / outlen] // 2. data = V. // 3. W = the Null string. @@ -251,10 +266,10 @@ public class HashSP800DRBG byte[] W = new byte[lengthInBits / 8]; - byte[] dig; + byte[] dig = new byte[_digest.getDigestSize()]; for (int i = 0; i <= m; i++) { - dig = hash(data); + doHash(data, dig); int bytesToCopy = ((W.length - i * dig.length) > dig.length) ? dig.length diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java index d7c58d33d..a1ec3b263 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/prng/drbg/SP80090DRBG.java @@ -5,6 +5,13 @@ package org.spongycastle.crypto.prng.drbg; */ public interface SP80090DRBG { + /** + * Return the block size of the DRBG. + * + * @return the block size (in bits) produced by each round of the DRBG. + */ + int getBlockSize(); + /** * Populate a passed in array with random data. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java index c15a81feb..243752e59 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSADigestSigner.java @@ -5,9 +5,9 @@ import java.math.BigInteger; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERSequence; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DSA; @@ -142,8 +142,8 @@ public class DSADigestSigner throws IOException { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERInteger(r)); - v.add(new DERInteger(s)); + v.add(new ASN1Integer(r)); + v.add(new ASN1Integer(s)); return new DERSequence(v).getEncoded(ASN1Encoding.DER); } @@ -156,8 +156,8 @@ public class DSADigestSigner return new BigInteger[] { - ((DERInteger)s.getObjectAt(0)).getValue(), - ((DERInteger)s.getObjectAt(1)).getValue() + ((ASN1Integer)s.getObjectAt(0)).getValue(), + ((ASN1Integer)s.getObjectAt(1)).getValue() }; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java index 4d9b87842..c4988d2b1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSASigner.java @@ -45,18 +45,19 @@ public class DSASigner boolean forSigning, CipherParameters param) { + SecureRandom providedRandom = null; + if (forSigning) { if (param instanceof ParametersWithRandom) { - ParametersWithRandom rParam = (ParametersWithRandom)param; + ParametersWithRandom rParam = (ParametersWithRandom)param; - this.random = rParam.getRandom(); this.key = (DSAPrivateKeyParameters)rParam.getParameters(); + providedRandom = rParam.getRandom(); } else { - this.random = new SecureRandom(); this.key = (DSAPrivateKeyParameters)param; } } @@ -64,6 +65,8 @@ public class DSASigner { this.key = (DSAPublicKeyParameters)param; } + + this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom); } /** @@ -157,4 +160,9 @@ public class DSASigner return new BigInteger(1, trunc); } } + + protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided) + { + return !needed ? null : (provided != null) ? provided : new SecureRandom(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java index 4aba32e4f..f938f5cfc 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/DSTU4145Signer.java @@ -13,7 +13,9 @@ import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; import org.spongycastle.util.Arrays; /** @@ -57,9 +59,9 @@ public class DSTU4145Signer public BigInteger[] generateSignature(byte[] message) { - ECDomainParameters parameters = key.getParameters(); + ECDomainParameters ec = key.getParameters(); - ECCurve curve = parameters.getCurve(); + ECCurve curve = ec.getCurve(); ECFieldElement h = hash2FieldElement(curve, message); if (h.isZero()) @@ -67,10 +69,14 @@ public class DSTU4145Signer h = curve.fromBigInteger(ONE); } - BigInteger n = parameters.getN(); + BigInteger n = ec.getN(); BigInteger e, r, s; ECFieldElement Fe, y; + BigInteger d = ((ECPrivateKeyParameters)key).getD(); + + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + do { do @@ -78,7 +84,7 @@ public class DSTU4145Signer do { e = generateRandomInteger(n, random); - Fe = parameters.getG().multiply(e).normalize().getAffineXCoord(); + Fe = basePointMultiplier.multiply(ec.getG(), e).normalize().getAffineXCoord(); } while (Fe.isZero()); @@ -87,7 +93,7 @@ public class DSTU4145Signer } while (r.signum() == 0); - s = r.multiply(((ECPrivateKeyParameters)key).getD()).add(e).mod(n); + s = r.multiply(d).add(e).mod(n); } while (s.signum() == 0); @@ -129,6 +135,11 @@ public class DSTU4145Signer return fieldElement2Integer(n, y).compareTo(r) == 0; } + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } + /** * Generates random integer such, than its bit length is less than that of n */ @@ -136,40 +147,24 @@ public class DSTU4145Signer { return new BigInteger(n.bitLength() - 1, random); } - - private static void reverseBytes(byte[] bytes) - { - byte tmp; - - for (int i=0; icurve.getFieldSize()) - { - num = num.clearBit(num.bitLength() - 1); - } - - return curve.fromBigInteger(num); + byte[] data = Arrays.reverse(hash); + return curve.fromBigInteger(truncate(new BigInteger(1, data), curve.getFieldSize())); } - private static BigInteger fieldElement2Integer(BigInteger n, ECFieldElement fieldElement) + private static BigInteger fieldElement2Integer(BigInteger n, ECFieldElement fe) { - BigInteger num = fieldElement.toBigInteger(); - while (num.bitLength() >= n.bitLength()) - { - num = num.clearBit(num.bitLength() - 1); - } + return truncate(fe.toBigInteger(), n.bitLength() - 1); + } - return num; + private static BigInteger truncate(BigInteger x, int bitLength) + { + if (x.bitLength() > bitLength) + { + x = x.mod(ONE.shiftLeft(bitLength)); + } + return x; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java index bf2344c73..b0cfdf6cb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECDSASigner.java @@ -5,13 +5,16 @@ import java.security.SecureRandom; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DSA; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; /** * EC-DSA as described in X9.62 @@ -46,18 +49,19 @@ public class ECDSASigner boolean forSigning, CipherParameters param) { + SecureRandom providedRandom = null; + if (forSigning) { if (param instanceof ParametersWithRandom) { - ParametersWithRandom rParam = (ParametersWithRandom)param; + ParametersWithRandom rParam = (ParametersWithRandom)param; - this.random = rParam.getRandom(); this.key = (ECPrivateKeyParameters)rParam.getParameters(); + providedRandom = rParam.getRandom(); } else { - this.random = new SecureRandom(); this.key = (ECPrivateKeyParameters)param; } } @@ -65,6 +69,8 @@ public class ECDSASigner { this.key = (ECPublicKeyParameters)param; } + + this.random = initSecureRandom(forSigning && !kCalculator.isDeterministic(), providedRandom); } // 5.3 pg 28 @@ -78,50 +84,44 @@ public class ECDSASigner public BigInteger[] generateSignature( byte[] message) { - BigInteger n = key.getParameters().getN(); + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); BigInteger e = calculateE(n, message); - BigInteger r = null; - BigInteger s = null; + BigInteger d = ((ECPrivateKeyParameters)key).getD(); if (kCalculator.isDeterministic()) { - kCalculator.init(n, ((ECPrivateKeyParameters)key).getD(), message); + kCalculator.init(n, d, message); } else { kCalculator.init(n, random); } + BigInteger r, s; + + ECMultiplier basePointMultiplier = createBasePointMultiplier(); + // 5.3.2 do // generate s { - BigInteger k = null; - + BigInteger k; do // generate r { k = kCalculator.nextK(); - ECPoint p = key.getParameters().getG().multiply(k).normalize(); + ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize(); // 5.3.3 - BigInteger x = p.getAffineXCoord().toBigInteger(); - - r = x.mod(n); + r = p.getAffineXCoord().toBigInteger().mod(n); } while (r.equals(ZERO)); - BigInteger d = ((ECPrivateKeyParameters)key).getD(); - s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); } while (s.equals(ZERO)); - BigInteger[] res = new BigInteger[2]; - - res[0] = r; - res[1] = s; - - return res; + return new BigInteger[]{ r, s }; } // 5.4 pg 29 @@ -135,7 +135,8 @@ public class ECDSASigner BigInteger r, BigInteger s) { - BigInteger n = key.getParameters().getN(); + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); BigInteger e = calculateE(n, message); // r in the range [1,n-1] @@ -155,7 +156,7 @@ public class ECDSASigner BigInteger u1 = e.multiply(c).mod(n); BigInteger u2 = r.multiply(c).mod(n); - ECPoint G = key.getParameters().getG(); + ECPoint G = ec.getG(); ECPoint Q = ((ECPublicKeyParameters)key).getQ(); ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2).normalize(); @@ -171,7 +172,7 @@ public class ECDSASigner return v.equals(r); } - private BigInteger calculateE(BigInteger n, byte[] message) + protected BigInteger calculateE(BigInteger n, byte[] message) { int log2n = n.bitLength(); int messageBitLength = message.length * 8; @@ -183,4 +184,14 @@ public class ECDSASigner } return e; } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } + + protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided) + { + return !needed ? null : (provided != null) ? provided : new SecureRandom(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java index b565e6806..92cc56abb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECGOST3410Signer.java @@ -2,13 +2,16 @@ package org.spongycastle.crypto.signers; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DSA; +import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECMultiplier; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.ec.FixedPointCombMultiplier; import java.math.BigInteger; import java.security.SecureRandom; @@ -63,17 +66,20 @@ public class ECGOST3410Signer { mRev[i] = message[mRev.length - 1 - i]; } - - BigInteger e = new BigInteger(1, mRev); - BigInteger n = key.getParameters().getN(); - BigInteger r = null; - BigInteger s = null; + BigInteger e = new BigInteger(1, mRev); + + ECDomainParameters ec = key.getParameters(); + BigInteger n = ec.getN(); + BigInteger d = ((ECPrivateKeyParameters)key).getD(); + + BigInteger r, s; + + ECMultiplier basePointMultiplier = createBasePointMultiplier(); do // generate s { - BigInteger k = null; - + BigInteger k; do // generate r { do @@ -82,26 +88,17 @@ public class ECGOST3410Signer } while (k.equals(ECConstants.ZERO)); - ECPoint p = key.getParameters().getG().multiply(k).normalize(); + ECPoint p = basePointMultiplier.multiply(ec.getG(), k).normalize(); - BigInteger x = p.getAffineXCoord().toBigInteger(); - - r = x.mod(n); + r = p.getAffineXCoord().toBigInteger().mod(n); } while (r.equals(ECConstants.ZERO)); - BigInteger d = ((ECPrivateKeyParameters)key).getD(); - s = (k.multiply(e)).add(d.multiply(r)).mod(n); } while (s.equals(ECConstants.ZERO)); - BigInteger[] res = new BigInteger[2]; - - res[0] = r; - res[1] = s; - - return res; + return new BigInteger[]{ r, s }; } /** @@ -155,4 +152,9 @@ public class ECGOST3410Signer return R.equals(r); } + + protected ECMultiplier createBasePointMultiplier() + { + return new FixedPointCombMultiplier(); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java index b2e1b4560..2fa90fb2b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ECNRSigner.java @@ -101,7 +101,7 @@ public class ECNRSigner // BigInteger Vx = tempPair.getPublic().getW().getAffineX(); ECPublicKeyParameters V = (ECPublicKeyParameters)tempPair.getPublic(); // get temp's public key - BigInteger Vx = V.getQ().normalize().getAffineXCoord().toBigInteger(); // get the point's x coordinate + BigInteger Vx = V.getQ().getAffineXCoord().toBigInteger(); // get the point's x coordinate r = Vx.add(e).mod(n); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java index f609c3fda..81d5d7a65 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/GOST3410Signer.java @@ -1,11 +1,15 @@ package org.spongycastle.crypto.signers; +import java.math.BigInteger; +import java.security.SecureRandom; + import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DSA; -import org.spongycastle.crypto.params.*; - -import java.security.SecureRandom; -import java.math.BigInteger; +import org.spongycastle.crypto.params.GOST3410KeyParameters; +import org.spongycastle.crypto.params.GOST3410Parameters; +import org.spongycastle.crypto.params.GOST3410PrivateKeyParameters; +import org.spongycastle.crypto.params.GOST3410PublicKeyParameters; +import org.spongycastle.crypto.params.ParametersWithRandom; /** * GOST R 34.10-94 Signature Algorithm @@ -25,7 +29,7 @@ public class GOST3410Signer { if (param instanceof ParametersWithRandom) { - ParametersWithRandom rParam = (ParametersWithRandom)param; + ParametersWithRandom rParam = (ParametersWithRandom)param; this.random = rParam.getRandom(); this.key = (GOST3410PrivateKeyParameters)rParam.getParameters(); @@ -99,7 +103,7 @@ public class GOST3410Signer } BigInteger m = new BigInteger(1, mRev); - GOST3410Parameters params = key.getParameters(); + GOST3410Parameters params = key.getParameters(); BigInteger zero = BigInteger.valueOf(0); if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java index bb17e477f..e919673f9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/HMacDSAKCalculator.java @@ -113,37 +113,28 @@ public class HMacDSAKCalculator hMac.doFinal(V, 0); - if (t.length - tOff < V.length) - { - System.arraycopy(V, 0, t, tOff, t.length - tOff); - tOff += t.length - tOff; - } - else - { - System.arraycopy(V, 0, t, tOff, V.length); - tOff += V.length; - } + int len = Math.min(t.length - tOff, V.length); + System.arraycopy(V, 0, t, tOff, len); + tOff += len; } BigInteger k = bitsToInt(t); - if (k.equals(ZERO) || k.compareTo(n) >= 0) - { - hMac.update(V, 0, V.length); - hMac.update((byte)0x00); - - hMac.doFinal(K, 0); - - hMac.init(new KeyParameter(K)); - - hMac.update(V, 0, V.length); - - hMac.doFinal(V, 0); - } - else + if (k.compareTo(ZERO) > 0 && k.compareTo(n) < 0) { return k; } + + hMac.update(V, 0, V.length); + hMac.update((byte)0x00); + + hMac.doFinal(K, 0); + + hMac.init(new KeyParameter(K)); + + hMac.update(V, 0, V.length); + + hMac.doFinal(V, 0); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java index 8f27d71bf..5ebb1e28f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/ISO9796d2PSSSigner.java @@ -17,7 +17,7 @@ import org.spongycastle.util.Integers; /** * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3). - * + * * Note: the usual length for the salt is the length of the hash * function used in bytes. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java index 494b72f7a..2fe248e46 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/signers/RSADigestSigner.java @@ -48,6 +48,8 @@ public class RSADigestSigner oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256); oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384); oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512); + oidMap.put("SHA-512/224", NISTObjectIdentifiers.id_sha512_224); + oidMap.put("SHA-512/256", NISTObjectIdentifiers.id_sha512_256); oidMap.put("MD2", PKCSObjectIdentifiers.md2); oidMap.put("MD4", PKCSObjectIdentifiers.md4); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java index ecf7fa984..a9504beff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsContext.java @@ -2,9 +2,21 @@ package org.spongycastle.crypto.tls; import java.security.SecureRandom; +import org.spongycastle.crypto.prng.DigestRandomGenerator; +import org.spongycastle.crypto.prng.RandomGenerator; +import org.spongycastle.util.Times; + abstract class AbstractTlsContext implements TlsContext { + private static long counter = Times.nanoTime(); + + private synchronized static long nextCounterValue() + { + return ++counter; + } + + private RandomGenerator nonceRandom; private SecureRandom secureRandom; private SecurityParameters securityParameters; @@ -15,10 +27,21 @@ abstract class AbstractTlsContext AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters) { + secureRandom.setSeed(nextCounterValue()); + secureRandom.setSeed(Times.nanoTime()); + + this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256)); + this.nonceRandom.addSeedMaterial(secureRandom.generateSeed(32)); + this.secureRandom = secureRandom; this.securityParameters = securityParameters; } + public RandomGenerator getNonceRandomGenerator() + { + return nonceRandom; + } + public SecureRandom getSecureRandom() { return secureRandom; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java index 238e49336..cf90455f2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsPeer.java @@ -5,6 +5,17 @@ import java.io.IOException; public abstract class AbstractTlsPeer implements TlsPeer { + public boolean shouldUseGMTUnixTime() + { + /* + * draft-mathewson-no-gmtunixtime-00 2. For the reasons we discuss above, we recommend that + * TLS implementors MUST by default set the entire value the ClientHello.Random and + * ServerHello.Random fields, including gmt_unix_time, to a cryptographically random + * sequence. + */ + return false; + } + public void notifySecureRenegotiation(boolean secureRenegotiation) throws IOException { if (!secureRenegotiation) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java index 30152dd0c..f4ffdfdd2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AbstractTlsServer.java @@ -19,6 +19,7 @@ public abstract class AbstractTlsServer protected short[] offeredCompressionMethods; protected Hashtable clientExtensions; + protected boolean encryptThenMACOffered; protected short maxFragmentLengthOffered; protected boolean truncatedHMacOffered; protected Vector supportedSignatureAlgorithms; @@ -41,6 +42,11 @@ public abstract class AbstractTlsServer this.cipherFactory = cipherFactory; } + protected boolean allowEncryptThenMAC() + { + return true; + } + protected boolean allowTruncatedHMac() { return false; @@ -85,7 +91,8 @@ public abstract class AbstractTlsServer for (int i = 0; i < namedCurves.length; ++i) { int namedCurve = namedCurves[i]; - if (!NamedCurve.refersToASpecificNamedCurve(namedCurve) || TlsECCUtils.isSupportedNamedCurve(namedCurve)) + if (NamedCurve.isValid(namedCurve) + && (!NamedCurve.refersToASpecificNamedCurve(namedCurve) || TlsECCUtils.isSupportedNamedCurve(namedCurve))) { return true; } @@ -125,6 +132,7 @@ public abstract class AbstractTlsServer if (clientExtensions != null) { + this.encryptThenMACOffered = TlsExtensionsUtils.hasEncryptThenMACExtension(clientExtensions); this.maxFragmentLengthOffered = TlsExtensionsUtils.getMaxFragmentLengthExtension(clientExtensions); this.truncatedHMacOffered = TlsExtensionsUtils.hasTruncatedHMacExtension(clientExtensions); @@ -197,9 +205,9 @@ public abstract class AbstractTlsServer { int cipherSuite = cipherSuites[i]; - // TODO Certain cipher suites may only be available starting at a particular version if (Arrays.contains(this.offeredCipherSuites, cipherSuite) - && (eccCipherSuitesEnabled || !TlsECCUtils.isECCCipherSuite(cipherSuite))) + && (eccCipherSuitesEnabled || !TlsECCUtils.isECCCipherSuite(cipherSuite)) + && TlsUtils.isValidCipherSuiteForVersion(cipherSuite, serverVersion)) { return this.selectedCipherSuite = cipherSuite; } @@ -225,6 +233,19 @@ public abstract class AbstractTlsServer public Hashtable getServerExtensions() throws IOException { + if (this.encryptThenMACOffered && allowEncryptThenMAC()) + { + /* + * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC + * request extension from a client and then selects a stream or AEAD cipher suite, it + * MUST NOT send an encrypt-then-MAC response extension back to the client. + */ + if (TlsUtils.isBlockCipherSuite(this.selectedCipherSuite)) + { + TlsExtensionsUtils.addEncryptThenMACExtension(checkServerExtensions()); + } + } + if (this.maxFragmentLengthOffered >= 0) { TlsExtensionsUtils.addMaxFragmentLengthExtension(checkServerExtensions(), this.maxFragmentLengthOffered); @@ -242,8 +263,8 @@ public abstract class AbstractTlsServer * message including a Supported Point Formats Extension appends this extension (along * with others) to its ServerHello message, enumerating the point formats it can parse. */ - this.serverECPointFormats = new short[]{ ECPointFormat.ansiX962_compressed_char2, - ECPointFormat.ansiX962_compressed_prime, ECPointFormat.uncompressed }; + this.serverECPointFormats = new short[]{ ECPointFormat.uncompressed, + ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, }; TlsECCUtils.addSupportedPointFormatsExtension(checkServerExtensions(), serverECPointFormats); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java index 3392c2a66..2ba4542ff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlertLevel.java @@ -1,7 +1,7 @@ package org.spongycastle.crypto.tls; /** - * RFC 2246 7.2 + * RFC 5246 7.2 */ public class AlertLevel { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java index de13e8503..990a98f91 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/AlwaysValidVerifyer.java @@ -2,7 +2,6 @@ package org.spongycastle.crypto.tls; /** * A certificate verifyer, that will always return true. - *
** DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING. *diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java index c7382fe81..e56cd7139 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/BulkCipherAlgorithm.java @@ -2,13 +2,12 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - * + ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ public class BulkCipherAlgorithm { - public static final int _null = 0; public static final int rc4 = 1; public static final int rc2 = 2; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java index d3cf8bf5d..ce21ddafb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ByteQueue.java @@ -8,7 +8,7 @@ public class ByteQueue /** * @return The smallest number which can be written as 2^x which is bigger than i. */ - public static final int nextTwoPow(int i) + public static int nextTwoPow(int i) { /* * This code is based of a lot of code I found on the Internet which mostly @@ -30,7 +30,7 @@ public class ByteQueue /** * The buffer where we store our data. */ - private byte[] databuf;; + private byte[] databuf; /** * How many bytes at the beginning of the buffer are skipped. @@ -62,15 +62,15 @@ public class ByteQueue */ public void read(byte[] buf, int offset, int len, int skip) { - if ((available - skip) < len) - { - throw new TlsRuntimeException("Not enough data to read"); - } if ((buf.length - offset) < len) { - throw new TlsRuntimeException("Buffer size of " + buf.length + throw new IllegalArgumentException("Buffer size of " + buf.length + " is too small for a read of " + len + " bytes"); } + if ((available - skip) < len) + { + throw new IllegalStateException("Not enough data to read"); + } System.arraycopy(databuf, skipped + skip, buf, offset, len); } @@ -112,7 +112,7 @@ public class ByteQueue { if (i > available) { - throw new TlsRuntimeException("Cannot remove " + i + " bytes, only got " + available); + throw new IllegalStateException("Cannot remove " + i + " bytes, only got " + available); } /* diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java index 2af17ea1f..df2a20331 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Certificate.java @@ -11,12 +11,11 @@ import org.spongycastle.asn1.ASN1Primitive; /** * Parsing and encoding of a Certificate struct from RFC 4346. - *
*- * opaque ASN.1Cert<2^24-1>; + * opaque ASN.1Cert<2^24-1>; * * struct { - * ASN.1Cert certificate_list<0..2^24-1>; + * ASN.1Cert certificate_list<0..2^24-1>; * } Certificate; ** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java index a4e5bf9e8..ae40206b4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CertificateRequest.java @@ -12,11 +12,10 @@ import org.spongycastle.asn1.x500.X500Name; /** * Parsing and encoding of a CertificateRequest struct from RFC 4346. - * ** struct { - * ClientCertificateType certificate_types<1..2^8-1>; - * DistinguishedName certificate_authorities<3..2^16-1>; + * ClientCertificateType certificate_types<1..2^8-1>; + * DistinguishedName certificate_authorities<3..2^16-1>; * } CertificateRequest; ** @@ -29,11 +28,6 @@ public class CertificateRequest protected Vector supportedSignatureAlgorithms; protected Vector certificateAuthorities; - /* - * TODO RFC 5264 7.4.4 A list of the hash/signature algorithm pairs that the server is able to - * verify, listed in descending order of preference. - */ - /** * @param certificateTypes see {@link ClientCertificateType} for valid constants. * @param certificateAuthorities a {@link Vector} of {@link X500Name}. @@ -47,7 +41,7 @@ public class CertificateRequest /** * @return an array of certificate types - * @see {@link ClientCertificateType} + * @see ClientCertificateType */ public short[] getCertificateTypes() { @@ -108,7 +102,7 @@ public class CertificateRequest X500Name certificateAuthority = (X500Name)certificateAuthorities.elementAt(i); byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER); derEncodings.addElement(derEncoding); - totalLength += derEncoding.length; + totalLength += derEncoding.length + 2; } TlsUtils.checkUint16(totalLength); @@ -116,8 +110,8 @@ public class CertificateRequest for (int i = 0; i < derEncodings.size(); ++i) { - byte[] encDN = (byte[])derEncodings.elementAt(i); - output.write(encDN); + byte[] derEncoding = (byte[])derEncodings.elementAt(i); + TlsUtils.writeOpaque16(derEncoding, output); } } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java new file mode 100644 index 000000000..aa2c89606 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/Chacha20Poly1305.java @@ -0,0 +1,156 @@ +package org.spongycastle.crypto.tls; + +import java.io.IOException; + +import org.spongycastle.crypto.Mac; +import org.spongycastle.crypto.engines.ChaChaEngine; +import org.spongycastle.crypto.generators.Poly1305KeyGenerator; +import org.spongycastle.crypto.macs.Poly1305; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Pack; + +public class Chacha20Poly1305 implements TlsCipher +{ + protected TlsContext context; + + protected ChaChaEngine encryptCipher; + protected ChaChaEngine decryptCipher; + + public Chacha20Poly1305(TlsContext context) throws IOException + { + if (!TlsUtils.isTLSv12(context)) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + + this.context = context; + + byte[] key_block = TlsUtils.calculateKeyBlock(context, 64); + + KeyParameter client_write_key = new KeyParameter(key_block, 0, 32); + KeyParameter server_write_key = new KeyParameter(key_block, 32, 32); + + this.encryptCipher = new ChaChaEngine(20); + this.decryptCipher = new ChaChaEngine(20); + + KeyParameter encryptKey, decryptKey; + if (context.isServer()) + { + encryptKey = server_write_key; + decryptKey = client_write_key; + } + else + { + encryptKey = client_write_key; + decryptKey = server_write_key; + } + + byte[] dummyNonce = new byte[8]; + + this.encryptCipher.init(true, new ParametersWithIV(encryptKey, dummyNonce)); + this.decryptCipher.init(false, new ParametersWithIV(decryptKey, dummyNonce)); + } + + public int getPlaintextLimit(int ciphertextLimit) + { + return ciphertextLimit - 16; + } + + public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len) throws IOException + { + int ciphertextLength = len + 16; + + KeyParameter macKey = initRecordMAC(encryptCipher, true, seqNo); + + byte[] output = new byte[ciphertextLength]; + encryptCipher.processBytes(plaintext, offset, len, output, 0); + + byte[] additionalData = getAdditionalData(seqNo, type, len); + byte[] mac = calculateRecordMAC(macKey, additionalData, output, 0, len); + System.arraycopy(mac, 0, output, len, mac.length); + + return output; + } + + public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len) throws IOException + { + if (getPlaintextLimit(len) < 0) + { + throw new TlsFatalAlert(AlertDescription.decode_error); + } + + int plaintextLength = len - 16; + + byte[] receivedMAC = Arrays.copyOfRange(ciphertext, offset + plaintextLength, offset + len); + + KeyParameter macKey = initRecordMAC(decryptCipher, false, seqNo); + + byte[] additionalData = getAdditionalData(seqNo, type, plaintextLength); + byte[] calculatedMAC = calculateRecordMAC(macKey, additionalData, ciphertext, offset, plaintextLength); + + if (!Arrays.constantTimeAreEqual(calculatedMAC, receivedMAC)) + { + throw new TlsFatalAlert(AlertDescription.bad_record_mac); + } + + byte[] output = new byte[plaintextLength]; + decryptCipher.processBytes(ciphertext, offset, plaintextLength, output, 0); + + return output; + } + + protected KeyParameter initRecordMAC(ChaChaEngine cipher, boolean forEncryption, long seqNo) + { + byte[] nonce = new byte[8]; + TlsUtils.writeUint64(seqNo, nonce, 0); + + cipher.init(forEncryption, new ParametersWithIV(null, nonce)); + + byte[] firstBlock = new byte[64]; + cipher.processBytes(firstBlock, 0, firstBlock.length, firstBlock, 0); + + // NOTE: The BC implementation puts 'r' after 'k' + System.arraycopy(firstBlock, 0, firstBlock, 32, 16); + KeyParameter macKey = new KeyParameter(firstBlock, 16, 32); + Poly1305KeyGenerator.clamp(macKey.getKey()); + return macKey; + } + + protected byte[] calculateRecordMAC(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len) + { + Mac mac = new Poly1305(); + mac.init(macKey); + + updateRecordMAC(mac, additionalData, 0, additionalData.length); + updateRecordMAC(mac, buf, off, len); + + byte[] output = new byte[mac.getMacSize()]; + mac.doFinal(output, 0); + return output; + } + + protected void updateRecordMAC(Mac mac, byte[] buf, int off, int len) + { + mac.update(buf, off, len); + + byte[] longLen = Pack.longToLittleEndian(len & 0xFFFFFFFFL); + mac.update(longLen, 0, longLen.length); + } + + protected byte[] getAdditionalData(long seqNo, short type, int len) throws IOException + { + /* + * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version + + * TLSCompressed.length + */ + byte[] additional_data = new byte[13]; + TlsUtils.writeUint64(seqNo, additional_data, 0); + TlsUtils.writeUint8(type, additional_data, 8); + TlsUtils.writeVersion(context.getServerVersion(), additional_data, 9); + TlsUtils.writeUint16(len, additional_data, 11); + + return additional_data; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java index f55031ba8..420f0d29a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherSuite.java @@ -56,7 +56,7 @@ public class CipherSuite public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A; /* - * RFC 4132 + * RFC 5932 */ public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041; public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042; @@ -64,6 +64,7 @@ public class CipherSuite public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044; public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045; public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046; + public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084; public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085; public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086; @@ -71,6 +72,20 @@ public class CipherSuite public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088; public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089; + public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA; + public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB; + public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC; + public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD; + public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE; + public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF; + + public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0; + public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1; + public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2; + public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3; + public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4; + public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5; + /* * RFC 4162 */ @@ -239,6 +254,54 @@ public class CipherSuite */ public static final int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF; + /* + * RFC 6367 + */ + public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072; + public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073; + public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074; + public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075; + public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076; + public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077; + public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078; + public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079; + + public static final int TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A; + public static final int TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B; + public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C; + public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D; + public static final int TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E; + public static final int TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F; + public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080; + public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081; + public static final int TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082; + public static final int TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083; + public static final int TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084; + public static final int TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085; + public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086; + public static final int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087; + public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088; + public static final int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089; + public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A; + public static final int TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B; + public static final int TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C; + public static final int TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D; + + public static final int TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E; + public static final int TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F; + public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090; + public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091; + public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092; + public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093; + public static final int TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094; + public static final int TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095; + public static final int TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096; + public static final int TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097; + public static final int TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098; + public static final int TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099; + public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A; + public static final int TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B; + /* * RFC 6655 */ @@ -260,38 +323,29 @@ public class CipherSuite public static final int TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB; /* - * TBD[draft-josefsson-salsa20-tls-02] + * draft-agl-tls-chacha20poly1305-04 */ - static final int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF00; - static final int TLS_RSA_WITH_SALSA20_SHA1 = 0xFF01; - static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF02; - static final int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xFF03; - static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF04; - static final int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xFF05; - static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xFF06; - static final int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xFF07; - static final int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF08; - static final int TLS_PSK_WITH_SALSA20_SHA1 = 0xFF09; - static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0A; - static final int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xFF0B; - static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0C; - static final int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xFF0D; - static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xFF0E; - static final int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xFF0F; - static final int TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF10; - static final int TLS_RSA_WITH_SALSA20_UMAC96 = 0xFF11; - static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF12; - static final int TLS_DHE_RSA_WITH_SALSA20_UMAC96 = 0xFF13; - static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF14; - static final int TLS_ECDHE_RSA_WITH_SALSA20_UMAC96 = 0xFF15; - static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF16; - static final int TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96 = 0xFF17; - static final int TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF18; - static final int TLS_PSK_WITH_SALSA20_UMAC96 = 0xFF19; - static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1A; - static final int TLS_DHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1B; - static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1C; - static final int TLS_RSA_PSK_WITH_SALSA20_UMAC96 = 0xFF1D; - static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96 = 0xFF1E; - static final int TLS_ECDHE_PSK_WITH_SALSA20_UMAC96 = 0xFF1F; + public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13; + public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14; + public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15; + + /* + * draft-josefsson-salsa20-tls-04 + */ + public static final int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE410; + public static final int TLS_RSA_WITH_SALSA20_SHA1 = 0xE411; + public static final int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE412; + public static final int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xE413; + public static final int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE414; + public static final int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xE415; + public static final int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE416; + public static final int TLS_PSK_WITH_SALSA20_SHA1 = 0xE417; + public static final int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE418; + public static final int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xE419; + public static final int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41A; + public static final int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xE41B; + public static final int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41C; + public static final int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xE41D; + public static final int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE41E; + public static final int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xE41F; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java index d260668ea..253da6f6d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/CipherType.java @@ -2,13 +2,12 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - * + ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ public class CipherType { - public static final int stream = 0; public static final int block = 1; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java index 85d03fda5..90eb48f2b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientAuthenticationType.java @@ -2,7 +2,6 @@ package org.spongycastle.crypto.tls; public class ClientAuthenticationType { - /* * RFC 5077 4 */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java index e7fcef58b..35752b079 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ClientCertificateType.java @@ -2,7 +2,6 @@ package org.spongycastle.crypto.tls; public class ClientCertificateType { - /* * RFC 4346 7.4.4 */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java index dd9f284c2..4964eff72 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ConnectionEnd.java @@ -2,13 +2,12 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ public class ConnectionEnd { - public static final int server = 0; public static final int client = 1; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java index 70cf373e8..f5a4f80c6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSClientProtocol.java @@ -32,11 +32,14 @@ public class DTLSClientProtocol SecurityParameters securityParameters = new SecurityParameters(); securityParameters.entity = ConnectionEnd.client; - securityParameters.clientRandom = TlsProtocol.createRandomBlock(secureRandom); ClientHandshakeState state = new ClientHandshakeState(); state.client = client; state.clientContext = new TlsClientContextImpl(secureRandom, securityParameters); + + securityParameters.clientRandom = TlsProtocol.createRandomBlock(client.shouldUseGMTUnixTime(), + state.clientContext.getNonceRandomGenerator()); + client.init(state.clientContext); DTLSRecordLayer recordLayer = new DTLSRecordLayer(transport, state.clientContext, client, ContentType.handshake); @@ -618,7 +621,8 @@ public class DTLSClientProtocol state.selectedCipherSuite = TlsUtils.readUint16(buf); if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite) || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } @@ -714,6 +718,19 @@ public class DTLSClientProtocol } } + /* + * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC + * request extension from a client and then selects a stream or AEAD cipher suite, it + * MUST NOT send an encrypt-then-MAC response extension back to the client. + */ + boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(serverExtensions); + if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(state.selectedCipherSuite)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + securityParameters.encryptThenMAC = serverSentEncryptThenMAC; + state.maxFragmentLength = evaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions, AlertDescription.illegal_parameter); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java index 6d87f9a5c..33dda1c71 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSEpoch.java @@ -2,7 +2,6 @@ package org.spongycastle.crypto.tls; class DTLSEpoch { - private final DTLSReplayWindow replayWindow = new DTLSReplayWindow(); private final int epoch; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java index 60ca4fe1f..13d5db006 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSProtocol.java @@ -68,23 +68,11 @@ public abstract class DTLSProtocol protected static void validateSelectedCipherSuite(int selectedCipherSuite, short alertDescription) throws IOException { - switch (selectedCipherSuite) + switch (TlsUtils.getEncryptionAlgorithm(selectedCipherSuite)) { - case CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: - case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: - case CipherSuite.TLS_DH_anon_WITH_RC4_128_MD5: - case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA: - // TODO Alert - throw new IllegalStateException("RC4 MUST NOT be used with DTLS"); + case EncryptionAlgorithm.RC4_40: + case EncryptionAlgorithm.RC4_128: + throw new TlsFatalAlert(alertDescription); } } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java index d88b636c6..810d69797 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReassembler.java @@ -4,7 +4,6 @@ import java.util.Vector; class DTLSReassembler { - private final short msg_type; private final byte[] body; @@ -28,9 +27,8 @@ class DTLSReassembler } void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset, - int fragment_length) + int fragment_length) { - int fragment_end = fragment_offset + fragment_length; if (this.msg_type != msg_type || this.body.length != length || fragment_end > length) @@ -104,7 +102,6 @@ class DTLSReassembler private static class Range { - private int start, end; Range(int start, int end) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java index 6586599fb..1f798d5af 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSRecordLayer.java @@ -245,10 +245,6 @@ class DTLSRecordLayer closeTransport(); } } - else - { - // TODO What exception? - } continue; } @@ -515,6 +511,6 @@ class DTLSRecordLayer private static long getMacSequenceNumber(int epoch, long sequence_number) { - return ((long)epoch << 48) | sequence_number; + return ((epoch & 0xFFFFFFFFL) << 48) | sequence_number; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java index df03fe264..d89dabca9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReliableHandshake.java @@ -107,7 +107,7 @@ class DTLSReliableHandshake // TODO Check the conditions under which we should reset this int readTimeoutMillis = 1000; - for (; ; ) + for (;;) { int receiveLimit = recordLayer.getReceiveLimit(); if (buf == null || buf.length < receiveLimit) @@ -160,13 +160,11 @@ class DTLSReliableHandshake .valueOf(seq)); if (reassembler != null) { - reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length); if (checkAll(previousInboundFlight)) { - resendOutboundFlight(); /* @@ -182,7 +180,6 @@ class DTLSReliableHandshake } else { - DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq)); if (reassembler == null) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java index 1ce21b5b3..d7db51c3b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSReplayWindow.java @@ -7,7 +7,6 @@ package org.spongycastle.crypto.tls; */ class DTLSReplayWindow { - private static final long VALID_SEQ_MASK = 0x0000FFFFFFFFFFFFL; private static final long WINDOW_SIZE = 64L; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java index 1d05711e4..6adb61e5f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSServerProtocol.java @@ -46,11 +46,14 @@ public class DTLSServerProtocol SecurityParameters securityParameters = new SecurityParameters(); securityParameters.entity = ConnectionEnd.server; - securityParameters.serverRandom = TlsProtocol.createRandomBlock(secureRandom); ServerHandshakeState state = new ServerHandshakeState(); state.server = server; state.serverContext = new TlsServerContextImpl(secureRandom, securityParameters); + + securityParameters.serverRandom = TlsProtocol.createRandomBlock(server.shouldUseGMTUnixTime(), + state.serverContext.getNonceRandomGenerator()); + server.init(state.serverContext); DTLSRecordLayer recordLayer = new DTLSRecordLayer(transport, state.serverContext, server, ContentType.handshake); @@ -340,7 +343,8 @@ public class DTLSServerProtocol state.selectedCipherSuite = state.server.getSelectedCipherSuite(); if (!Arrays.contains(state.offeredCipherSuites, state.selectedCipherSuite) || state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + || state.selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || !TlsUtils.isValidCipherSuiteForVersion(state.selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.internal_error); } @@ -388,6 +392,8 @@ public class DTLSServerProtocol if (state.serverExtensions != null) { + securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(state.serverExtensions); + state.maxFragmentLength = evaluateMaxFragmentLengthExtension(state.clientExtensions, state.serverExtensions, AlertDescription.internal_error); @@ -472,10 +478,18 @@ public class DTLSServerProtocol TlsProtocol.assertEmpty(buf); // Verify the CertificateVerify message contains a correct signature. + boolean verified = false; try { - // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned - byte[] certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null); + byte[] certificateVerifyHash; + if (TlsUtils.isTLSv12(state.serverContext)) + { + certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash()); + } + else + { + certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null); + } org.spongycastle.asn1.x509.Certificate x509Cert = state.clientCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); @@ -483,10 +497,14 @@ public class DTLSServerProtocol TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType); tlsSigner.init(state.serverContext); - tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(), + verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(), clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash); } catch (Exception e) + { + } + + if (!verified) { throw new TlsFatalAlert(AlertDescription.decrypt_error); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java index 2df9ef7ce..ba6377b10 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DTLSTransport.java @@ -5,7 +5,6 @@ import java.io.IOException; public class DTLSTransport implements DatagramTransport { - private final DTLSRecordLayer recordLayer; DTLSTransport(DTLSRecordLayer recordLayer) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java index 761029b04..9ceac9ef3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DatagramTransport.java @@ -4,7 +4,6 @@ import java.io.IOException; public interface DatagramTransport { - int getReceiveLimit() throws IOException; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java index aa41af0b5..9c1c68a48 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsCipherFactory.java @@ -4,20 +4,18 @@ import java.io.IOException; import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.Mac; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.digests.MD5Digest; import org.spongycastle.crypto.digests.SHA1Digest; import org.spongycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.digests.SHA384Digest; import org.spongycastle.crypto.digests.SHA512Digest; -import org.spongycastle.crypto.engines.AESFastEngine; +import org.spongycastle.crypto.engines.AESEngine; import org.spongycastle.crypto.engines.CamelliaEngine; import org.spongycastle.crypto.engines.DESedeEngine; import org.spongycastle.crypto.engines.RC4Engine; import org.spongycastle.crypto.engines.SEEDEngine; import org.spongycastle.crypto.engines.Salsa20Engine; -import org.spongycastle.crypto.macs.HMac; import org.spongycastle.crypto.modes.AEADBlockCipher; import org.spongycastle.crypto.modes.CBCBlockCipher; import org.spongycastle.crypto.modes.CCMBlockCipher; @@ -33,6 +31,9 @@ public class DefaultTlsCipherFactory { case EncryptionAlgorithm._3DES_EDE_CBC: return createDESedeCipher(context, macAlgorithm); + case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305: + // NOTE: Ignores macAlgorithm + return createChaCha20Poly1305(context); case EncryptionAlgorithm.AES_128_CBC: return createAESCipher(context, 16, macAlgorithm); case EncryptionAlgorithm.AES_128_CCM: @@ -57,8 +58,14 @@ public class DefaultTlsCipherFactory return createCipher_AES_GCM(context, 32, 16); case EncryptionAlgorithm.CAMELLIA_128_CBC: return createCamelliaCipher(context, 16, macAlgorithm); + case EncryptionAlgorithm.CAMELLIA_128_GCM: + // NOTE: Ignores macAlgorithm + return createCipher_Camellia_GCM(context, 16, 16); case EncryptionAlgorithm.CAMELLIA_256_CBC: return createCamelliaCipher(context, 32, macAlgorithm); + case EncryptionAlgorithm.CAMELLIA_256_GCM: + // NOTE: Ignores macAlgorithm + return createCipher_Camellia_GCM(context, 32, 16); case EncryptionAlgorithm.ESTREAM_SALSA20: return createSalsa20Cipher(context, 12, 32, macAlgorithm); case EncryptionAlgorithm.NULL: @@ -81,6 +88,19 @@ public class DefaultTlsCipherFactory createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize); } + protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm) + throws IOException + { + return new TlsBlockCipher(context, createCamelliaBlockCipher(), + createCamelliaBlockCipher(), createHMACDigest(macAlgorithm), + createHMACDigest(macAlgorithm), cipherKeySize); + } + + protected TlsCipher createChaCha20Poly1305(TlsContext context) throws IOException + { + return new Chacha20Poly1305(context); + } + protected TlsAEADCipher createCipher_AES_CCM(TlsContext context, int cipherKeySize, int macSize) throws IOException { @@ -95,12 +115,11 @@ public class DefaultTlsCipherFactory createAEADBlockCipher_AES_GCM(), cipherKeySize, macSize); } - protected TlsBlockCipher createCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm) + protected TlsAEADCipher createCipher_Camellia_GCM(TlsContext context, int cipherKeySize, int macSize) throws IOException { - return new TlsBlockCipher(context, createCamelliaBlockCipher(), - createCamelliaBlockCipher(), createHMACDigest(macAlgorithm), - createHMACDigest(macAlgorithm), cipherKeySize); + return new TlsAEADCipher(context, createAEADBlockCipher_Camellia_GCM(), + createAEADBlockCipher_Camellia_GCM(), cipherKeySize, macSize); } protected TlsBlockCipher createDESedeCipher(TlsContext context, int macAlgorithm) @@ -121,18 +140,14 @@ public class DefaultTlsCipherFactory throws IOException { return new TlsStreamCipher(context, createRC4StreamCipher(), createRC4StreamCipher(), - createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize); + createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, false); } protected TlsStreamCipher createSalsa20Cipher(TlsContext context, int rounds, int cipherKeySize, int macAlgorithm) throws IOException { - /* - * TODO To be able to support UMAC96, we need to give the TlsStreamCipher a Mac instead of - * assuming HMAC and passing a digest. - */ return new TlsStreamCipher(context, createSalsa20StreamCipher(rounds), createSalsa20StreamCipher(rounds), - createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize); + createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), cipherKeySize, true); } protected TlsBlockCipher createSEEDCipher(TlsContext context, int macAlgorithm) @@ -142,25 +157,41 @@ public class DefaultTlsCipherFactory createHMACDigest(macAlgorithm), createHMACDigest(macAlgorithm), 16); } + protected BlockCipher createAESEngine() + { + return new AESEngine(); + } + + protected BlockCipher createCamelliaEngine() + { + return new CamelliaEngine(); + } + protected BlockCipher createAESBlockCipher() { - return new CBCBlockCipher(new AESFastEngine()); + return new CBCBlockCipher(createAESEngine()); } protected AEADBlockCipher createAEADBlockCipher_AES_CCM() { - return new CCMBlockCipher(new AESFastEngine()); + return new CCMBlockCipher(createAESEngine()); } protected AEADBlockCipher createAEADBlockCipher_AES_GCM() { // TODO Consider allowing custom configuration of multiplier - return new GCMBlockCipher(new AESFastEngine()); + return new GCMBlockCipher(createAESEngine()); + } + + protected AEADBlockCipher createAEADBlockCipher_Camellia_GCM() + { + // TODO Consider allowing custom configuration of multiplier + return new GCMBlockCipher(createCamelliaEngine()); } protected BlockCipher createCamelliaBlockCipher() { - return new CBCBlockCipher(new CamelliaEngine()); + return new CBCBlockCipher(createCamelliaEngine()); } protected BlockCipher createDESedeBlockCipher() @@ -190,29 +221,17 @@ public class DefaultTlsCipherFactory case MACAlgorithm._null: return null; case MACAlgorithm.hmac_md5: - return new MD5Digest(); + return TlsUtils.createHash(HashAlgorithm.md5); case MACAlgorithm.hmac_sha1: - return new SHA1Digest(); + return TlsUtils.createHash(HashAlgorithm.sha1); case MACAlgorithm.hmac_sha256: - return new SHA256Digest(); + return TlsUtils.createHash(HashAlgorithm.sha256); case MACAlgorithm.hmac_sha384: - return new SHA384Digest(); + return TlsUtils.createHash(HashAlgorithm.sha384); case MACAlgorithm.hmac_sha512: - return new SHA512Digest(); + return TlsUtils.createHash(HashAlgorithm.sha512); default: throw new TlsFatalAlert(AlertDescription.internal_error); } } - - protected Mac createMac(int macAlgorithm) throws IOException - { - switch (macAlgorithm) - { - // TODO Need an implementation of UMAC -// case MACAlgorithm.umac96: -// return - default: - return new HMac(createHMACDigest(macAlgorithm)); - } - } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java index 603481239..0c17b0329 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsClient.java @@ -17,10 +17,15 @@ public abstract class DefaultTlsClient public int[] getCipherSuites() { - return new int[] { CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA }; + return new int[] + { + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, + }; } public TlsKeyExchange getKeyExchange() @@ -36,7 +41,11 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); @@ -48,7 +57,11 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); @@ -60,7 +73,11 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS); @@ -76,11 +93,14 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96: case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA); @@ -91,6 +111,10 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); @@ -102,6 +126,10 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); @@ -113,12 +141,15 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96: return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: @@ -128,12 +159,15 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96: return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: @@ -148,16 +182,18 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_RSA_WITH_NULL_MD5: case CipherSuite.TLS_RSA_WITH_NULL_SHA: case CipherSuite.TLS_RSA_WITH_NULL_SHA256: case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96: case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: return createRSAKeyExchange(); @@ -187,6 +223,11 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null); + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: @@ -278,6 +319,28 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: @@ -285,18 +348,36 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384); + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96); - case CipherSuite.TLS_RSA_WITH_NULL_MD5: return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5); @@ -326,12 +407,6 @@ public abstract class DefaultTlsClient case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96); - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java index 417405ed8..53f9315e2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsEncryptionCredentials.java @@ -9,8 +9,7 @@ import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.crypto.params.RSAKeyParameters; -public class DefaultTlsEncryptionCredentials - extends AbstractTlsEncryptionCredentials +public class DefaultTlsEncryptionCredentials extends AbstractTlsEncryptionCredentials { protected TlsContext context; protected Certificate certificate; @@ -58,18 +57,6 @@ public class DefaultTlsEncryptionCredentials public byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret) throws IOException { - - PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine()); - encoding.init(false, new ParametersWithRandom(this.privateKey, context.getSecureRandom())); - - try - { - return encoding.processBlock(encryptedPreMasterSecret, 0, - encryptedPreMasterSecret.length); - } - catch (InvalidCipherTextException e) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } + return TlsRSAUtils.safeDecryptPreMasterSecret(context, (RSAKeyParameters)privateKey, encryptedPreMasterSecret); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java index 95cca885f..3a2ac3b2e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DefaultTlsServer.java @@ -8,7 +8,6 @@ import org.spongycastle.crypto.params.DHParameters; public abstract class DefaultTlsServer extends AbstractTlsServer { - public DefaultTlsServer() { super(); @@ -38,11 +37,21 @@ public abstract class DefaultTlsServer protected int[] getCipherSuites() { - return new int[]{CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, - CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,}; + return new int[] + { + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, + CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, + }; } public TlsCredentials getCredentials() @@ -62,7 +71,11 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_NULL_MD5: case CipherSuite.TLS_RSA_WITH_NULL_SHA: case CipherSuite.TLS_RSA_WITH_NULL_SHA256: @@ -83,7 +96,12 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: @@ -92,8 +110,15 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: return getRSASignerCredentials(); default: @@ -117,7 +142,11 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS); @@ -129,7 +158,11 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA); @@ -141,7 +174,11 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS); @@ -157,11 +194,14 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96: case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA); @@ -172,6 +212,10 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA); @@ -183,6 +227,10 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA); @@ -194,12 +242,15 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96: return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA); case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: @@ -209,12 +260,15 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96: return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA); case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: @@ -229,16 +283,18 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_RSA_WITH_NULL_MD5: case CipherSuite.TLS_RSA_WITH_NULL_SHA: case CipherSuite.TLS_RSA_WITH_NULL_SHA256: case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96: case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: return createRSAKeyExchange(); @@ -266,6 +322,11 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MACAlgorithm._null); + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: @@ -357,6 +418,28 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: @@ -364,18 +447,36 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha1); + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha256); + + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null); + + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384); + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96); - case CipherSuite.TLS_RSA_WITH_NULL_MD5: return cipherFactory.createCipher(context, EncryptionAlgorithm.NULL, MACAlgorithm.hmac_md5); @@ -405,12 +506,6 @@ public abstract class DefaultTlsServer case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_WITH_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96); - case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java index 9f3cb5570..a1459553f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/DigestAlgorithm.java @@ -2,7 +2,7 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java index 678384f9c..3a8d6a574 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ECBasisType.java @@ -5,7 +5,11 @@ package org.spongycastle.crypto.tls; */ public class ECBasisType { - public static final short ec_basis_trinomial = 1; public static final short ec_basis_pentanomial = 2; + + public static boolean isValid(short ecBasisType) + { + return ecBasisType >= ec_basis_trinomial && ecBasisType <= ec_basis_pentanomial; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java index 6b607726a..9fcc72992 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/EncryptionAlgorithm.java @@ -2,13 +2,12 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ public class EncryptionAlgorithm { - public static final int NULL = 0; public static final int RC4_40 = 1; public static final int RC4_128 = 2; @@ -31,7 +30,7 @@ public class EncryptionAlgorithm public static final int AES_256_GCM = 11; /* - * RFC 4132 + * RFC 5932 */ public static final int CAMELLIA_128_CBC = 12; public static final int CAMELLIA_256_CBC = 13; @@ -50,8 +49,19 @@ public class EncryptionAlgorithm public static final int AES_256_CCM_8 = 18; /* - * TBD[draft-josefsson-salsa20-tls-02] + * RFC 6367 */ - static final int ESTREAM_SALSA20 = 100; - static final int SALSA20 = 101; + public static final int CAMELLIA_128_GCM = 19; + public static final int CAMELLIA_256_GCM = 20; + + /* + * draft-josefsson-salsa20-tls-04 + */ + public static final int ESTREAM_SALSA20 = 100; + public static final int SALSA20 = 101; + + /* + * draft-agl-tls-chacha20poly1305-04 + */ + public static final int AEAD_CHACHA20_POLY1305 = 102; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java index 0b50769de..9047d1dbd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ExtensionType.java @@ -28,11 +28,6 @@ public class ExtensionType */ public static final int srp = 12; - /* - * RFC 5077 7. - */ - public static final int session_ticket = 35; - /* * RFC 5246 7.4.1.4. */ @@ -48,6 +43,16 @@ public class ExtensionType */ public static final int heartbeat = 15; + /* + * RFC 5077 7. + */ + public static final int session_ticket = 35; + + /* + * draft-ietf-tls-encrypt-then-mac-03 + */ + public static final int encrypt_then_mac = 22; + /* * RFC 5746 3.2. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java index 60fc2529b..e09005b0f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/HeartbeatMessage.java @@ -50,7 +50,7 @@ public class HeartbeatMessage output.write(payload); byte[] padding = new byte[paddingLength]; - context.getSecureRandom().nextBytes(padding); + context.getNonceRandomGenerator().nextBytes(padding); output.write(padding); } @@ -87,6 +87,9 @@ public class HeartbeatMessage int padding_length = buf.size() - payload.length; + /* + * RFC 6520 4. The padding of a received HeartbeatMessage message MUST be ignored + */ return new HeartbeatMessage(type, payload, padding_length); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java index 4c41bac49..868344612 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/KeyExchangeAlgorithm.java @@ -2,7 +2,7 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java index 9f2ad384f..5b522b6ce 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MACAlgorithm.java @@ -2,7 +2,7 @@ package org.spongycastle.crypto.tls; /** * RFC 2246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ @@ -20,9 +20,4 @@ public class MACAlgorithm public static final int hmac_sha256 = 3; public static final int hmac_sha384 = 4; public static final int hmac_sha512 = 5; - - /* - * TBD[draft-josefsson-salsa20-tls-02] - */ - static final int umac96 = 100; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java index 12aa8f37b..6d864114c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/MaxFragmentLength.java @@ -5,10 +5,10 @@ public class MaxFragmentLength /* * RFC 3546 3.2. */ - public static short pow2_9 = 1; - public static short pow2_10 = 2; - public static short pow2_11 = 3; - public static short pow2_12 = 4; + public static final short pow2_9 = 1; + public static final short pow2_10 = 2; + public static final short pow2_11 = 3; + public static final short pow2_12 = 4; public static boolean isValid(short maxFragmentLength) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java index ec40602f1..8f733587a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/NamedCurve.java @@ -2,7 +2,7 @@ package org.spongycastle.crypto.tls; /** * RFC 4492 5.1.1 - *
+ ** The named curves defined here are those specified in SEC 2 [13]. Note that many of these curves * are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00 through 0xFEFF are * reserved for private use. Values 0xFF01 and 0xFF02 indicate that the client supports arbitrary @@ -51,6 +51,12 @@ public class NamedCurve public static final int arbitrary_explicit_prime_curves = 0xFF01; public static final int arbitrary_explicit_char2_curves = 0xFF02; + public static boolean isValid(int namedCurve) + { + return (namedCurve >= sect163k1 && namedCurve <= brainpoolP512r1) + || (namedCurve >= arbitrary_explicit_prime_curves && namedCurve <= arbitrary_explicit_char2_curves); + } + public static boolean refersToASpecificNamedCurve(int namedCurve) { switch (namedCurve) @@ -62,5 +68,4 @@ public class NamedCurve return true; } } - } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java index d95bea9bd..25c45deb0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/OCSPStatusRequest.java @@ -90,11 +90,11 @@ public class OCSPStatusRequest } /** - * Parse a {@link OCSPStatusRequest} from an {@link InputStream}. + * Parse an {@link OCSPStatusRequest} from an {@link InputStream}. * * @param input * the {@link InputStream} to parse from. - * @return a {@link OCSPStatusRequest} object. + * @return an {@link OCSPStatusRequest} object. * @throws IOException */ public static OCSPStatusRequest parse(InputStream input) throws IOException diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java index 62abbec63..63da881e1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PRFAlgorithm.java @@ -2,13 +2,12 @@ package org.spongycastle.crypto.tls; /** * RFC 5246 - *
+ ** Note that the values here are implementation-specific and arbitrary. It is recommended not to * depend on the particular values (e.g. serialization). */ public class PRFAlgorithm { - /* * Placeholder to refer to the legacy TLS algorithm */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java index 2955c1c00..318535e1f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/PSKTlsClient.java @@ -39,14 +39,16 @@ public abstract class PSKTlsClient case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_UMAC96: case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: return createPSKKeyExchange(KeyExchangeAlgorithm.DHE_PSK); @@ -56,14 +58,14 @@ public abstract class PSKTlsClient case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96: return createPSKKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK); case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: @@ -77,14 +79,16 @@ public abstract class PSKTlsClient case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_PSK_WITH_NULL_SHA: case CipherSuite.TLS_PSK_WITH_NULL_SHA256: case CipherSuite.TLS_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_PSK_WITH_SALSA20_UMAC96: return createPSKKeyExchange(KeyExchangeAlgorithm.PSK); case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: @@ -94,14 +98,16 @@ public abstract class PSKTlsClient case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_UMAC96: return createPSKKeyExchange(KeyExchangeAlgorithm.RSA_PSK); default: @@ -174,18 +180,34 @@ public abstract class PSKTlsClient case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_GCM, MACAlgorithm._null); + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_CBC, MACAlgorithm.hmac_sha256); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_128_GCM, MACAlgorithm._null); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_CBC, MACAlgorithm.hmac_sha384); + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + return cipherFactory.createCipher(context, EncryptionAlgorithm.CAMELLIA_256_GCM, MACAlgorithm._null); + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.ESTREAM_SALSA20, MACAlgorithm.umac96); - case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: case CipherSuite.TLS_PSK_WITH_NULL_SHA: @@ -216,12 +238,6 @@ public abstract class PSKTlsClient case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.hmac_sha1); - case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_PSK_WITH_SALSA20_UMAC96: - case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_UMAC96: - return cipherFactory.createCipher(context, EncryptionAlgorithm.SALSA20, MACAlgorithm.umac96); - default: /* * Note: internal error here; the TlsProtocol implementation verifies that the diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java index 3aeefe42b..2bd9a0a88 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/ProtocolVersion.java @@ -2,6 +2,8 @@ package org.spongycastle.crypto.tls; import java.io.IOException; +import org.spongycastle.util.Strings; + public final class ProtocolVersion { public static final ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0"); @@ -45,6 +47,11 @@ public final class ProtocolVersion return this == SSLv3; } + public boolean isTLS() + { + return getMajorVersion() == 0x03; + } + public ProtocolVersion getEquivalentTLSVersion() { if (!isDTLS()) @@ -78,9 +85,14 @@ public final class ProtocolVersion return isDTLS() ? diffMinorVersion > 0 : diffMinorVersion < 0; } - public boolean equals(Object obj) + public boolean equals(Object other) { - return this == obj; + return this == other || (other instanceof ProtocolVersion && equals((ProtocolVersion)other)); + } + + public boolean equals(ProtocolVersion other) + { + return other != null && this.version == other.version; } public int hashCode() @@ -94,6 +106,7 @@ public final class ProtocolVersion switch (major) { case 0x03: + { switch (minor) { case 0x00: @@ -105,21 +118,41 @@ public final class ProtocolVersion case 0x03: return TLSv12; } + return getUnknownVersion(major, minor, "TLS"); + } case 0xFE: + { switch (minor) { case 0xFF: return DTLSv10; + case 0xFE: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); case 0xFD: return DTLSv12; } + return getUnknownVersion(major, minor, "DTLS"); + } + default: + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } } - - throw new TlsFatalAlert(AlertDescription.illegal_parameter); } public String toString() { return name; } + + private static ProtocolVersion getUnknownVersion(int major, int minor, String prefix) + throws IOException + { + TlsUtils.checkUint8(major); + TlsUtils.checkUint8(minor); + + int v = (major << 8) | minor; + String hex = Strings.toUpperCase(Integer.toHexString(0x10000 | v).substring(1)); + return new ProtocolVersion(v, prefix + " 0x" + hex); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java index 01cc00526..3e1b3873a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/RecordStream.java @@ -5,8 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import org.spongycastle.crypto.Digest; - /** * An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3. */ @@ -219,6 +217,12 @@ class RecordStream protected void writeRecord(short type, byte[] plaintext, int plaintextOffset, int plaintextLength) throws IOException { + // Never send anything until a valid ClientHello has been received + if (writeVersion == null) + { + return; + } + /* * RFC 5264 6. Implementations MUST NOT send record types not defined in this document * unless negotiated by some extension. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java index bd4e37f95..6b3f2faf3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SSL3Mac.java @@ -8,9 +8,9 @@ import org.spongycastle.util.Arrays; /** * HMAC implementation based on original internet draft for HMAC (RFC 2104) - *
+ ** The difference is that padding is concatenated versus XORed with the key - *
+ ** H(K + opad, H(K + ipad, text)) */ public class SSL3Mac diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java index c5d543946..36648311b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SecurityParameters.java @@ -16,6 +16,7 @@ public class SecurityParameters // TODO Keep these internal, since it's maybe not the ideal place for them short maxFragmentLength = -1; boolean truncatedHMac = false; + boolean encryptThenMAC = false; void copySessionParametersFrom(SecurityParameters other) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java index 43cf38cee..5da3b27ba 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAlgorithm.java @@ -5,7 +5,6 @@ package org.spongycastle.crypto.tls; */ public class SignatureAlgorithm { - public static final short anonymous = 0; public static final short rsa = 1; public static final short dsa = 2; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java index 1c1827e56..211c96c3d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/SignatureAndHashAlgorithm.java @@ -75,8 +75,8 @@ public class SignatureAndHashAlgorithm public void encode(OutputStream output) throws IOException { - TlsUtils.writeUint8(hash, output); - TlsUtils.writeUint8(signature, output); + TlsUtils.writeUint8(getHash(), output); + TlsUtils.writeUint8(getSignature(), output); } /** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java index c7fe94969..8926d6fb0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsAgreementCredentials.java @@ -7,7 +7,6 @@ import org.spongycastle.crypto.params.AsymmetricKeyParameter; public interface TlsAgreementCredentials extends TlsCredentials { - byte[] generateAgreement(AsymmetricKeyParameter peerPublicKey) throws IOException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java index bb290c77c..4dd675952 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsBlockCipher.java @@ -11,16 +11,15 @@ import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; /** - * A generic TLS 1.0-1.1 / SSLv3 block cipher. This can be used for AES or 3DES for example. + * A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example. */ public class TlsBlockCipher implements TlsCipher { - private static boolean encryptThenMAC = false; - protected TlsContext context; protected byte[] randomData; protected boolean useExplicitIV; + private boolean encryptThenMAC; protected BlockCipher encryptCipher; protected BlockCipher decryptCipher; @@ -44,9 +43,10 @@ public class TlsBlockCipher this.context = context; this.randomData = new byte[256]; - context.getSecureRandom().nextBytes(randomData); + context.getNonceRandomGenerator().nextBytes(randomData); this.useExplicitIV = TlsUtils.isTLSv11(context); + this.encryptThenMAC = context.getSecurityParameters().encryptThenMAC; int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize() + serverWriteDigest.getDigestSize(); @@ -183,7 +183,7 @@ public class TlsBlockCipher if (useExplicitIV) { byte[] explicitIV = new byte[blockSize]; - context.getSecureRandom().nextBytes(explicitIV); + context.getNonceRandomGenerator().nextBytes(explicitIV); encryptCipher.init(true, new ParametersWithIV(null, explicitIV)); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java index 8f0d3fefa..31b2bacf8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsCipherFactory.java @@ -4,7 +4,6 @@ import java.io.IOException; public interface TlsCipherFactory { - /** * See enumeration classes EncryptionAlgorithm, MACAlgorithm for appropriate argument values */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java index 2b56d4257..bce220618 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClient.java @@ -36,9 +36,9 @@ public interface TlsClient /** * Notifies the client of the session_id sent in the ServerHello. - * + * * @param sessionID - * @see {@link TlsContext#getResumableSession()} + * @see TlsContext#getResumableSession() */ void notifySessionID(byte[] sessionID); @@ -66,7 +66,7 @@ public interface TlsClient /** * RFC 5077 3.3. NewSessionTicket Handshake Message - *
+ ** This method will be called (only) when a NewSessionTicket handshake message is received. The * ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption * that it complies with e.g. RFC 5077 4. Recommended Ticket Construction. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java index c6b56a9e8..b50bd7d82 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsClientProtocol.java @@ -43,6 +43,9 @@ public class TlsClientProtocol return random; } + /** + * @deprecated use alternate constructor taking an explicit {@link SecureRandom} + */ public TlsClientProtocol(InputStream input, OutputStream output) { this(input, output, createSecureRandom()); @@ -74,9 +77,12 @@ public class TlsClientProtocol this.securityParameters = new SecurityParameters(); this.securityParameters.entity = ConnectionEnd.client; - this.securityParameters.clientRandom = createRandomBlock(secureRandom); this.tlsClientContext = new TlsClientContextImpl(secureRandom, securityParameters); + + this.securityParameters.clientRandom = createRandomBlock(tlsClient.shouldUseGMTUnixTime(), + tlsClientContext.getNonceRandomGenerator()); + this.tlsClient.init(tlsClientContext); this.recordStream.init(tlsClientContext); @@ -214,6 +220,19 @@ public class TlsClientProtocol switch (this.connection_state) { case CS_CLIENT_FINISHED: + { + if (this.expectSessionTicket) + { + /* + * RFC 5077 3.3. This message MUST be sent if the server included a + * SessionTicket extension in the ServerHello. + */ + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } + + // NB: Fall through to next case label + } + case CS_SERVER_SESSION_TICKET: { processFinishedMessage(buf); this.connection_state = CS_SERVER_FINISHED; @@ -621,12 +640,13 @@ public class TlsClientProtocol /* * Find out which CipherSuite the server has chosen and check that it was one of the offered - * ones. + * ones, and is a valid selection for the negotiated version. */ int selectedCipherSuite = TlsUtils.readUint16(buf); if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } @@ -755,6 +775,19 @@ public class TlsClientProtocol if (sessionServerExtensions != null) { + /* + * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC + * request extension from a client and then selects a stream or AEAD cipher suite, it + * MUST NOT send an encrypt-then-MAC response extension back to the client. + */ + boolean serverSentEncryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(sessionServerExtensions); + if (serverSentEncryptThenMAC && !TlsUtils.isBlockCipherSuite(selectedCipherSuite)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + this.securityParameters.encryptThenMAC = serverSentEncryptThenMAC; + this.securityParameters.maxFragmentLength = processMaxFragmentLengthExtension(sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java index 5da0bb645..a47d1d6ea 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsContext.java @@ -2,8 +2,12 @@ package org.spongycastle.crypto.tls; import java.security.SecureRandom; +import org.spongycastle.crypto.prng.RandomGenerator; + public interface TlsContext { + RandomGenerator getNonceRandomGenerator(); + SecureRandom getSecureRandom(); SecurityParameters getSecurityParameters(); @@ -20,7 +24,7 @@ public interface TlsContext * * @return A {@link TlsSession} representing the resumable session used by this connection, or * null if no resumable session available. - * @see {@link TlsPeer#notifyHandshakeComplete()} + * @see TlsPeer#notifyHandshakeComplete() */ TlsSession getResumableSession(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java index a2899fe06..ef4a8e477 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSASigner.java @@ -50,7 +50,7 @@ public abstract class TlsDSASigner public Signer createSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey) { - return makeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.context.getSecureRandom())); + return makeSigner(algorithm, false, true, privateKey); } public Signer createVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey) @@ -58,6 +58,11 @@ public abstract class TlsDSASigner return makeSigner(algorithm, false, false, publicKey); } + protected CipherParameters makeInitParameters(boolean forSigning, CipherParameters cp) + { + return cp; + } + protected Signer makeSigner(SignatureAndHashAlgorithm algorithm, boolean raw, boolean forSigning, CipherParameters cp) { @@ -66,20 +71,22 @@ public abstract class TlsDSASigner throw new IllegalStateException(); } + // TODO For TLS 1.2+, lift the SHA-1 restriction here if (algorithm != null && (algorithm.getHash() != HashAlgorithm.sha1 || algorithm.getSignature() != getSignatureAlgorithm())) { throw new IllegalStateException(); } - Digest d = raw ? new NullDigest() : TlsUtils.createHash(HashAlgorithm.sha1); + short hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.getHash(); + Digest d = raw ? new NullDigest() : TlsUtils.createHash(hashAlgorithm); - Signer s = new DSADigestSigner(createDSAImpl(), d); - s.init(forSigning, cp); + Signer s = new DSADigestSigner(createDSAImpl(hashAlgorithm), d); + s.init(forSigning, makeInitParameters(forSigning, cp)); return s; } protected abstract short getSignatureAlgorithm(); - protected abstract DSA createDSAImpl(); + protected abstract DSA createDSAImpl(short hashAlgorithm); } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java index d4309c137..bc26c0364 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsDSSSigner.java @@ -4,6 +4,7 @@ import org.spongycastle.crypto.DSA; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.DSAPublicKeyParameters; import org.spongycastle.crypto.signers.DSASigner; +import org.spongycastle.crypto.signers.HMacDSAKCalculator; public class TlsDSSSigner extends TlsDSASigner @@ -13,9 +14,9 @@ public class TlsDSSSigner return publicKey instanceof DSAPublicKeyParameters; } - protected DSA createDSAImpl() + protected DSA createDSAImpl(short hashAlgorithm) { - return new DSASigner(); + return new DSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm))); } protected short getSignatureAlgorithm() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java index 52e836fcf..5f9adffb0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECCUtils.java @@ -12,14 +12,17 @@ import org.spongycastle.asn1.x9.ECNamedCurveTable; import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.agreement.ECDHBasicAgreement; +import org.spongycastle.crypto.ec.CustomNamedCurves; import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECFieldElement; import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.field.PolynomialExtensionField; import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; import org.spongycastle.util.Integers; @@ -70,11 +73,7 @@ public class TlsECCUtils public static byte[] createSupportedPointFormatsExtension(short[] ecPointFormats) throws IOException { - if (ecPointFormats == null) - { - ecPointFormats = new short[] { ECPointFormat.uncompressed }; - } - else if (!Arrays.contains(ecPointFormats, ECPointFormat.uncompressed)) + if (ecPointFormats == null || !Arrays.contains(ecPointFormats, ECPointFormat.uncompressed)) { /* * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST @@ -82,11 +81,7 @@ public class TlsECCUtils */ // NOTE: We add it at the end (lowest preference) - short[] tmp = new short[ecPointFormats.length + 1]; - System.arraycopy(ecPointFormats, 0, tmp, 0, ecPointFormats.length); - tmp[ecPointFormats.length] = ECPointFormat.uncompressed; - - ecPointFormats = tmp; + ecPointFormats = Arrays.append(ecPointFormats, ECPointFormat.uncompressed); } return TlsUtils.encodeUint8ArrayWithUint8Length(ecPointFormats); @@ -158,12 +153,16 @@ public class TlsECCUtils return null; } - // Lazily created the first time a particular curve is accessed - X9ECParameters ecP = ECNamedCurveTable.getByName(curveName); + // Parameters are lazily created the first time a particular curve is accessed + X9ECParameters ecP = CustomNamedCurves.getByName(curveName); if (ecP == null) { - return null; + ecP = ECNamedCurveTable.getByName(curveName); + if (ecP == null) + { + return null; + } } // It's a bit inefficient to do this conversion every time @@ -254,20 +253,44 @@ public class TlsECCUtils case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: /* - * draft-josefsson-salsa20-tls-02 + * RFC 6367 + */ + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + + /* + * draft-agl-tls-chacha20poly1305-04 + */ + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + + /* + * draft-josefsson-salsa20-tls-04 */ case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_UMAC96: case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: - case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_UMAC96: return true; @@ -325,14 +348,14 @@ public class TlsECCUtils * used. */ boolean compressed = false; - if (curve instanceof ECCurve.F2m) - { - compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_char2); - } - else if (curve instanceof ECCurve.Fp) + if (ECAlgorithms.isFpCurve(curve)) { compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_prime); } + else if (ECAlgorithms.isF2mCurve(curve)) + { + compressed = isCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_char2); + } return point.getEncoded(compressed); } @@ -354,12 +377,48 @@ public class TlsECCUtils public static ECPoint deserializeECPoint(short[] ecPointFormats, ECCurve curve, byte[] encoding) throws IOException { - /* - * NOTE: Here we implicitly decode compressed or uncompressed encodings. DefaultTlsClient by - * default is set up to advertise that we can parse any encoding so this works fine, but - * extra checks might be needed here if that were changed. - */ - // TODO Review handling of infinity and hybrid encodings + if (encoding == null || encoding.length < 1) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + short actualFormat; + switch (encoding[0]) + { + case 0x02: // compressed + case 0x03: // compressed + { + if (ECAlgorithms.isF2mCurve(curve)) + { + actualFormat = ECPointFormat.ansiX962_compressed_char2; + } + else if (ECAlgorithms.isFpCurve(curve)) + { + actualFormat = ECPointFormat.ansiX962_compressed_prime; + } + else + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + break; + } + case 0x04: // uncompressed + { + actualFormat = ECPointFormat.uncompressed; + break; + } + case 0x00: // infinity + case 0x06: // hybrid + case 0x07: // hybrid + default: + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + if (!Arrays.contains(ecPointFormats, actualFormat)) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + return curve.decodePoint(encoding); } @@ -401,7 +460,7 @@ public class TlsECCUtils public static ECPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, short[] ecPointFormats, ECDomainParameters ecParams, OutputStream output) throws IOException { - AsymmetricCipherKeyPair kp = TlsECCUtils.generateECKeyPair(random, ecParams); + AsymmetricCipherKeyPair kp = generateECKeyPair(random, ecParams); ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters) kp.getPublic(); writeECPoint(ecPointFormats, ecPublicKey.getQ(), output); @@ -456,10 +515,11 @@ public class TlsECCUtils BigInteger prime_p = readECParameter(input); BigInteger a = readECFieldElement(prime_p.bitLength(), input); BigInteger b = readECFieldElement(prime_p.bitLength(), input); - ECCurve curve = new ECCurve.Fp(prime_p, a, b); - ECPoint base = deserializeECPoint(ecPointFormats, curve, TlsUtils.readOpaque8(input)); + byte[] baseEncoding = TlsUtils.readOpaque8(input); BigInteger order = readECParameter(input); BigInteger cofactor = readECParameter(input); + ECCurve curve = new ECCurve.Fp(prime_p, a, b, order, cofactor); + ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding); return new ECDomainParameters(curve, base, order, cofactor); } case ECCurveType.explicit_char2: @@ -468,32 +528,30 @@ public class TlsECCUtils int m = TlsUtils.readUint16(input); short basis = TlsUtils.readUint8(input); - ECCurve curve; - switch (basis) { - case ECBasisType.ec_basis_trinomial: + if (!ECBasisType.isValid(basis)) { - int k = readECExponent(m, input); - BigInteger a = readECFieldElement(m, input); - BigInteger b = readECFieldElement(m, input); - curve = new ECCurve.F2m(m, k, a, b); - break; - } - case ECBasisType.ec_basis_pentanomial: - { - int k1 = readECExponent(m, input); - int k2 = readECExponent(m, input); - int k3 = readECExponent(m, input); - BigInteger a = readECFieldElement(m, input); - BigInteger b = readECFieldElement(m, input); - curve = new ECCurve.F2m(m, k1, k2, k3, a, b); - break; - } - default: throw new TlsFatalAlert(AlertDescription.illegal_parameter); } - ECPoint base = deserializeECPoint(ecPointFormats, curve, TlsUtils.readOpaque8(input)); + + int k1 = readECExponent(m, input), k2 = -1, k3 = -1; + if (basis == ECBasisType.ec_basis_pentanomial) + { + k2 = readECExponent(m, input); + k3 = readECExponent(m, input); + } + + BigInteger a = readECFieldElement(m, input); + BigInteger b = readECFieldElement(m, input); + byte[] baseEncoding = TlsUtils.readOpaque8(input); BigInteger order = readECParameter(input); BigInteger cofactor = readECParameter(input); + + ECCurve curve = (basis == ECBasisType.ec_basis_pentanomial) + ? new ECCurve.F2m(m, k1, k2, k3, a, b, order, cofactor) + : new ECCurve.F2m(m, k1, a, b, order, cofactor); + + ECPoint base = deserializeECPoint(ecPointFormats, curve, baseEncoding); + return new ECDomainParameters(curve, base, order, cofactor); } case ECCurveType.named_curve: @@ -511,7 +569,7 @@ public class TlsECCUtils checkNamedCurve(namedCurves, namedCurve); - return TlsECCUtils.getParametersForNamedCurve(namedCurve); + return getParametersForNamedCurve(namedCurve); } default: throw new TlsFatalAlert(AlertDescription.illegal_parameter); @@ -561,35 +619,40 @@ public class TlsECCUtils OutputStream output) throws IOException { ECCurve curve = ecParameters.getCurve(); - if (curve instanceof ECCurve.Fp) + + if (ECAlgorithms.isFpCurve(curve)) { TlsUtils.writeUint8(ECCurveType.explicit_prime, output); - ECCurve.Fp fp = (ECCurve.Fp) curve; - writeECParameter(fp.getQ(), output); + writeECParameter(curve.getField().getCharacteristic(), output); } - else if (curve instanceof ECCurve.F2m) + else if (ECAlgorithms.isF2mCurve(curve)) { + PolynomialExtensionField field = (PolynomialExtensionField)curve.getField(); + int[] exponents = field.getMinimalPolynomial().getExponentsPresent(); + TlsUtils.writeUint8(ECCurveType.explicit_char2, output); - ECCurve.F2m f2m = (ECCurve.F2m) curve; - int m = f2m.getM(); + int m = exponents[exponents.length - 1]; TlsUtils.checkUint16(m); TlsUtils.writeUint16(m, output); - if (f2m.isTrinomial()) + if (exponents.length == 3) { TlsUtils.writeUint8(ECBasisType.ec_basis_trinomial, output); - writeECExponent(f2m.getK1(), output); + writeECExponent(exponents[1], output); + } + else if (exponents.length == 5) + { + TlsUtils.writeUint8(ECBasisType.ec_basis_pentanomial, output); + writeECExponent(exponents[1], output); + writeECExponent(exponents[2], output); + writeECExponent(exponents[3], output); } else { - TlsUtils.writeUint8(ECBasisType.ec_basis_pentanomial, output); - writeECExponent(f2m.getK1(), output); - writeECExponent(f2m.getK2(), output); - writeECExponent(f2m.getK3(), output); + throw new IllegalArgumentException("Only trinomial and pentomial curves are supported"); } - } else { @@ -605,7 +668,7 @@ public class TlsECCUtils public static void writeECPoint(short[] ecPointFormats, ECPoint point, OutputStream output) throws IOException { - TlsUtils.writeOpaque8(TlsECCUtils.serializeECPoint(ecPointFormats, point), output); + TlsUtils.writeOpaque8(serializeECPoint(ecPointFormats, point), output); } public static void writeNamedECParameters(int namedCurve, OutputStream output) throws IOException diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java index c1a1021a8..d159368db 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDHEKeyExchange.java @@ -57,7 +57,7 @@ public class TlsECDHEKeyExchange for (int i = 0; i < namedCurves.length; ++i) { int entry = namedCurves[i]; - if (TlsECCUtils.isSupportedNamedCurve(entry)) + if (NamedCurve.isValid(entry) && TlsECCUtils.isSupportedNamedCurve(entry)) { namedCurve = entry; break; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java index c3bd67c98..308aabf00 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsECDSASigner.java @@ -4,6 +4,7 @@ import org.spongycastle.crypto.DSA; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.signers.ECDSASigner; +import org.spongycastle.crypto.signers.HMacDSAKCalculator; public class TlsECDSASigner extends TlsDSASigner @@ -13,9 +14,9 @@ public class TlsECDSASigner return publicKey instanceof ECPublicKeyParameters; } - protected DSA createDSAImpl() + protected DSA createDSAImpl(short hashAlgorithm) { - return new ECDSASigner(); + return new ECDSASigner(new HMacDSAKCalculator(TlsUtils.createHash(hashAlgorithm))); } protected short getSignatureAlgorithm() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java index a8e7d8882..c47363826 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsEncryptionCredentials.java @@ -2,8 +2,7 @@ package org.spongycastle.crypto.tls; import java.io.IOException; -public interface TlsEncryptionCredentials - extends TlsCredentials +public interface TlsEncryptionCredentials extends TlsCredentials { byte[] decryptPreMasterSecret(byte[] encryptedPreMasterSecret) throws IOException; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java index 07ccb199e..70393e0f0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsExtensionsUtils.java @@ -9,6 +9,7 @@ import org.spongycastle.util.Integers; public class TlsExtensionsUtils { + public static final Integer EXT_encrypt_then_mac = Integers.valueOf(ExtensionType.encrypt_then_mac); public static final Integer EXT_heartbeat = Integers.valueOf(ExtensionType.heartbeat); public static final Integer EXT_max_fragment_length = Integers.valueOf(ExtensionType.max_fragment_length); public static final Integer EXT_server_name = Integers.valueOf(ExtensionType.server_name); @@ -20,6 +21,11 @@ public class TlsExtensionsUtils return extensions == null ? new Hashtable() : extensions; } + public static void addEncryptThenMACExtension(Hashtable extensions) + { + extensions.put(EXT_encrypt_then_mac, createEncryptThenMACExtension()); + } + public static void addHeartbeatExtension(Hashtable extensions, HeartbeatExtension heartbeatExtension) throws IOException { @@ -77,6 +83,12 @@ public class TlsExtensionsUtils return extensionData == null ? null : readStatusRequestExtension(extensionData); } + public static boolean hasEncryptThenMACExtension(Hashtable extensions) throws IOException + { + byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_encrypt_then_mac); + return extensionData == null ? false : readEncryptThenMACExtension(extensionData); + } + public static boolean hasTruncatedHMacExtension(Hashtable extensions) throws IOException { byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_truncated_hmac); @@ -88,6 +100,11 @@ public class TlsExtensionsUtils return TlsUtils.EMPTY_BYTES; } + public static byte[] createEncryptThenMACExtension() + { + return createEmptyExtensionData(); + } + public static byte[] createHeartbeatExtension(HeartbeatExtension heartbeatExtension) throws IOException { @@ -149,6 +166,26 @@ public class TlsExtensionsUtils return createEmptyExtensionData(); } + private static boolean readEmptyExtensionData(byte[] extensionData) throws IOException + { + if (extensionData == null) + { + throw new IllegalArgumentException("'extensionData' cannot be null"); + } + + if (extensionData.length != 0) + { + throw new TlsFatalAlert(AlertDescription.illegal_parameter); + } + + return true; + } + + public static boolean readEncryptThenMACExtension(byte[] extensionData) throws IOException + { + return readEmptyExtensionData(extensionData); + } + public static HeartbeatExtension readHeartbeatExtension(byte[] extensionData) throws IOException { @@ -223,18 +260,8 @@ public class TlsExtensionsUtils return statusRequest; } - private static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException + public static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException { - if (extensionData == null) - { - throw new IllegalArgumentException("'extensionData' cannot be null"); - } - - if (extensionData.length != 0) - { - throw new TlsFatalAlert(AlertDescription.illegal_parameter); - } - - return true; + return readEmptyExtensionData(extensionData); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java index 1fb28d3c8..4fc82ffd1 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsHandshakeHash.java @@ -2,7 +2,7 @@ package org.spongycastle.crypto.tls; import org.spongycastle.crypto.Digest; -interface TlsHandshakeHash +public interface TlsHandshakeHash extends Digest { void init(TlsContext context); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java index 7f7de6977..e2c3e2816 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsInputStream.java @@ -17,6 +17,12 @@ class TlsInputStream this.handler = handler; } + public int available() + throws IOException + { + return this.handler.applicationDataAvailable(); + } + public int read(byte[] buf, int offset, int len) throws IOException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java index d0f2370a2..82902170d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsKeyExchange.java @@ -9,7 +9,6 @@ import java.io.OutputStream; */ public interface TlsKeyExchange { - void init(TlsContext context); void skipServerCredentials() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java index 33eb7f7b3..6390b6996 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsMac.java @@ -26,7 +26,7 @@ public class TlsMac * @param digest The digest to use. * @param key A byte-array where the key for this MAC is located. * @param keyOff The number of bytes to skip, before the key starts in the buffer. - * @param len The length of the key. + * @param keyLen The length of the key. */ public TlsMac(TlsContext context, Digest digest, byte[] key, int keyOff, int keyLen) { @@ -105,15 +105,6 @@ public class TlsMac */ public byte[] calculateMac(long seqNo, short type, byte[] message, int offset, int length) { - /* - * TODO[draft-josefsson-salsa20-tls-02] 3. Moreover, in order to accommodate MAC algorithms - * like UMAC that require a nonce as part of their operation, the document extends the MAC - * algorithm as specified in the TLS protocol. The extended MAC includes a nonce as a second - * parameter. MAC algorithms that do not require a nonce, such as HMAC, are assumed to - * ignore the nonce input value. The MAC in a GenericStreamCipher is then calculated as - * follows. - */ - ProtocolVersion serverVersion = context.getServerVersion(); boolean isSSL = serverVersion.isSSL(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java index 8dbc26c8f..62ed0f71e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsPeer.java @@ -4,6 +4,17 @@ import java.io.IOException; public interface TlsPeer { + /** + * draft-mathewson-no-gmtunixtime-00 2. "If existing users of a TLS implementation may rely on + * gmt_unix_time containing the current time, we recommend that implementors MAY provide the + * ability to set gmt_unix_time as an option only, off by default." + * + * @return
+ *true
if the current time should be used in the gmt_unix_time field of + * Random, orfalse
if gmt_unix_time should contain a cryptographically + * random value. + */ + boolean shouldUseGMTUnixTime(); + void notifySecureRenegotiation(boolean secureNegotiation) throws IOException; TlsCompression getCompression() throws IOException; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java index 1120279b0..96aff625b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocol.java @@ -12,6 +12,7 @@ import java.util.Hashtable; import java.util.Vector; import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.prng.RandomGenerator; import org.spongycastle.util.Arrays; import org.spongycastle.util.Integers; @@ -52,6 +53,7 @@ public abstract class TlsProtocol private ByteQueue applicationDataQueue = new ByteQueue(); private ByteQueue alertQueue = new ByteQueue(2); private ByteQueue handshakeQueue = new ByteQueue(); +// private ByteQueue heartbeatQueue = new ByteQueue(); /* * The Record Stream we use @@ -227,7 +229,13 @@ public abstract class TlsProtocol } case ContentType.heartbeat: { + if (!appDataReady) + { + throw new TlsFatalAlert(AlertDescription.unexpected_message); + } // TODO[RFC 6520] +// heartbeatQueue.addData(buf, offset, len); +// processHeartbeat(); } default: /* @@ -378,19 +386,27 @@ public abstract class TlsProtocol throw new TlsFatalAlert(AlertDescription.decode_error); } - if (this.receivedChangeCipherSpec) + if (this.receivedChangeCipherSpec + || alertQueue.size() > 0 + || handshakeQueue.size() > 0) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } + recordStream.receivedReadCipherSpec(); + this.receivedChangeCipherSpec = true; - recordStream.receivedReadCipherSpec(); - handleChangeCipherSpecMessage(); } } + protected int applicationDataAvailable() + throws IOException + { + return applicationDataQueue.size(); + } + /** * Read data from the network. The method will return immediately, if there is still some data * left in the buffer, or block until some application data has been read from the network. @@ -822,18 +838,16 @@ public abstract class TlsProtocol } } - protected static byte[] createRandomBlock(SecureRandom random) + protected static byte[] createRandomBlock(boolean useGMTUnixTime, RandomGenerator randomGenerator) { - random.setSeed(System.currentTimeMillis()); - byte[] result = new byte[32]; - random.nextBytes(result); - /* - * The consensus seems to be that using the time here is neither all that useful, nor - * secure. Perhaps there could be an option to (re-)enable it. Instead, we seed the random - * source with the current time to retain it's main benefit. - */ -// TlsUtils.writeGMTUnixTime(result, 0); + randomGenerator.nextBytes(result); + + if (useGMTUnixTime) + { + TlsUtils.writeGMTUnixTime(result, 0); + } + return result; } @@ -987,18 +1001,31 @@ public abstract class TlsProtocol switch (ciphersuite) { + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: @@ -1006,14 +1033,28 @@ public abstract class TlsProtocol case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: case CipherSuite.TLS_PSK_WITH_AES_128_CCM: @@ -1021,7 +1062,9 @@ public abstract class TlsProtocol case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: case CipherSuite.TLS_PSK_WITH_AES_256_CCM: case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: case CipherSuite.TLS_RSA_WITH_AES_128_CCM: case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: @@ -1029,6 +1072,9 @@ public abstract class TlsProtocol case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: case CipherSuite.TLS_RSA_WITH_AES_256_CCM: case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: case CipherSuite.TLS_RSA_WITH_NULL_SHA256: { if (isTLSv12) @@ -1038,22 +1084,39 @@ public abstract class TlsProtocol throw new TlsFatalAlert(AlertDescription.illegal_parameter); } + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: { if (isTLSv12) { @@ -1063,12 +1126,16 @@ public abstract class TlsProtocol } case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_PSK_WITH_NULL_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: { if (isTLSv12) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java index bd12e4dff..49dceb23c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsProtocolHandler.java @@ -10,7 +10,6 @@ import java.security.SecureRandom; public class TlsProtocolHandler extends TlsClientProtocol { - public TlsProtocolHandler(InputStream is, OutputStream os) { super(is, os); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java index b9ba5443c..10cace4bf 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAKeyExchange.java @@ -130,7 +130,7 @@ public class TlsRSAKeyExchange encryptedPreMasterSecret = TlsUtils.readOpaque16(input); } - this.premasterSecret = TlsRSAUtils.safeDecryptPreMasterSecret(context, serverCredentials, encryptedPreMasterSecret); + this.premasterSecret = serverCredentials.decryptPreMasterSecret(encryptedPreMasterSecret); } public byte[] generatePremasterSecret() diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java index 70ef035d7..ecc058b53 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRSAUtils.java @@ -8,6 +8,7 @@ import org.spongycastle.crypto.encodings.PKCS1Encoding; import org.spongycastle.crypto.engines.RSABlindedEngine; import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.crypto.params.RSAKeyParameters; +import org.spongycastle.util.Arrays; public class TlsRSAUtils { @@ -49,33 +50,48 @@ public class TlsRSAUtils return premasterSecret; } + /** + * @deprecated {@link TlsEncryptionCredentials#decryptPreMasterSecret(byte[])} is expected to decrypt safely + */ public static byte[] safeDecryptPreMasterSecret(TlsContext context, TlsEncryptionCredentials encryptionCredentials, + byte[] encryptedPreMasterSecret) throws IOException + { + return encryptionCredentials.decryptPreMasterSecret(encryptedPreMasterSecret); + } + + public static byte[] safeDecryptPreMasterSecret(TlsContext context, RSAKeyParameters rsaServerPrivateKey, byte[] encryptedPreMasterSecret) { /* * RFC 5246 7.4.7.1. */ - ProtocolVersion clientVersion = context.getClientVersion(); // TODO Provide as configuration option? boolean versionNumberCheckDisabled = false; /* - * See notes regarding Bleichenbacher/Klima attack. The code here implements the first - * construction proposed there, which is RECOMMENDED. + * Generate 48 random bytes we can use as a Pre-Master-Secret, if the + * PKCS1 padding check should fail. */ - byte[] R = new byte[48]; - context.getSecureRandom().nextBytes(R); + byte[] fallback = new byte[48]; + context.getSecureRandom().nextBytes(fallback); - byte[] M = TlsUtils.EMPTY_BYTES; + byte[] M = Arrays.clone(fallback); try { - M = encryptionCredentials.decryptPreMasterSecret(encryptedPreMasterSecret); + PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine(), fallback); + encoding.init(false, + new ParametersWithRandom(rsaServerPrivateKey, context.getSecureRandom())); + + M = encoding.processBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.length); } catch (Exception e) { /* + * This should never happen since the decryption should never throw an exception + * and return a random value instead. + * * In any case, a TLS server MUST NOT generate an alert if processing an * RSA-encrypted premaster secret message fails, or the version number is not as * expected. Instead, it MUST continue the handshake with a randomly generated @@ -83,12 +99,6 @@ public class TlsRSAUtils */ } - if (M.length != 48) - { - TlsUtils.writeVersion(clientVersion, R, 0); - return R; - } - /* * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST * check the version number [..]. @@ -96,21 +106,35 @@ public class TlsRSAUtils if (versionNumberCheckDisabled && clientVersion.isEqualOrEarlierVersionOf(ProtocolVersion.TLSv10)) { /* - * If the version number is TLS 1.0 or earlier, server implementations SHOULD - * check the version number, but MAY have a configuration option to disable the - * check. + * If the version number is TLS 1.0 or earlier, server + * implementations SHOULD check the version number, but MAY have a + * configuration option to disable the check. + * + * So there is nothing to do here. */ } else { /* - * Note that explicitly constructing the pre_master_secret with the - * ClientHello.client_version produces an invalid master_secret if the client - * has sent the wrong version in the original pre_master_secret. + * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the + * clientVersion received during the handshake. If they don't match, we replace the + * decrypted Pre-Master-Secret with a random one. */ - TlsUtils.writeVersion(clientVersion, M, 0); - } + int correct = (clientVersion.getMajorVersion() ^ (M[0] & 0xff)) + | (clientVersion.getMinorVersion() ^ (M[1] & 0xff)); + correct |= correct >> 1; + correct |= correct >> 2; + correct |= correct >> 4; + int mask = ~((correct & 1) - 1); + /* + * mask will be all bits set to 0xff if the version number differed. + */ + for (int i = 0; i < 48; i++) + { + M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask)); + } + } return M; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRuntimeException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRuntimeException.java deleted file mode 100644 index 97d30b9aa..000000000 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsRuntimeException.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.spongycastle.crypto.tls; - -public class TlsRuntimeException - extends RuntimeException -{ - private static final long serialVersionUID = 1928023487348344086L; - - Throwable e; - - public TlsRuntimeException(String message, Throwable e) - { - super(message); - - this.e = e; - } - - public TlsRuntimeException(String message) - { - super(message); - } - - public Throwable getCause() - { - return e; - } -} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java index 1b171ff4b..6e9072ed5 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPKeyExchange.java @@ -163,7 +163,7 @@ public class TlsSRPKeyExchange extends AbstractTlsKeyExchange throw new TlsFatalAlert(AlertDescription.illegal_parameter); } - this.srpClient.init(N, g, new SHA1Digest(), context.getSecureRandom()); + this.srpClient.init(N, g, TlsUtils.createHash(HashAlgorithm.sha1), context.getSecureRandom()); } public void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java index 74fac926f..48ddefb77 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsSRPUtils.java @@ -1,7 +1,6 @@ package org.spongycastle.crypto.tls; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Hashtable; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java index 3dcd14ff4..225963f39 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServer.java @@ -78,7 +78,7 @@ public interface TlsServer /** * RFC 5077 3.3. NewSessionTicket Handshake Message. - ** This method will be called (only) if a NewSessionTicket extension was sent by the server. See * RFC 5077 4. Recommended Ticket Construction for recommended format and protection. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java index 3411086e2..b4e3b04c6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsServerProtocol.java @@ -52,9 +52,12 @@ public class TlsServerProtocol this.securityParameters = new SecurityParameters(); this.securityParameters.entity = ConnectionEnd.server; - this.securityParameters.serverRandom = createRandomBlock(secureRandom); this.tlsServerContext = new TlsServerContextImpl(secureRandom, securityParameters); + + this.securityParameters.serverRandom = createRandomBlock(tlsServer.shouldUseGMTUnixTime(), + tlsServerContext.getNonceRandomGenerator()); + this.tlsServer.init(tlsServerContext); this.recordStream.init(tlsServerContext); @@ -430,10 +433,18 @@ public class TlsServerProtocol assertEmpty(buf); // Verify the CertificateVerify message contains a correct signature. + boolean verified = false; try { - // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned - byte[] certificateVerifyHash = getCurrentPRFHash(getContext(), prepareFinishHash, null); + byte[] certificateVerifyHash; + if (TlsUtils.isTLSv12(getContext())) + { + certificateVerifyHash = prepareFinishHash.getFinalHash(clientCertificateVerify.getAlgorithm().getHash()); + } + else + { + certificateVerifyHash = TlsProtocol.getCurrentPRFHash(getContext(), prepareFinishHash, null); + } org.spongycastle.asn1.x509.Certificate x509Cert = this.peerCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); @@ -441,10 +452,14 @@ public class TlsServerProtocol TlsSigner tlsSigner = TlsUtils.createTlsSigner(this.clientCertificateType); tlsSigner.init(getContext()); - tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(), + verified = tlsSigner.verifyRawSignature(clientCertificateVerify.getAlgorithm(), clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash); } catch (Exception e) + { + } + + if (!verified) { throw new TlsFatalAlert(AlertDescription.decrypt_error); } @@ -641,7 +656,8 @@ public class TlsServerProtocol int selectedCipherSuite = tlsServer.getSelectedCipherSuite(); if (!Arrays.contains(this.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL - || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV + || !TlsUtils.isValidCipherSuiteForVersion(selectedCipherSuite, server_version)) { throw new TlsFatalAlert(AlertDescription.internal_error); } @@ -694,6 +710,8 @@ public class TlsServerProtocol if (this.serverExtensions != null) { + this.securityParameters.encryptThenMAC = TlsExtensionsUtils.hasEncryptThenMACExtension(this.serverExtensions); + this.securityParameters.maxFragmentLength = processMaxFragmentLengthExtension(clientExtensions, this.serverExtensions, AlertDescription.internal_error); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java index ff065ee88..6394b391e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsStreamCipher.java @@ -6,13 +6,12 @@ import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.util.Arrays; public class TlsStreamCipher implements TlsCipher { - private static boolean encryptThenMAC = false; - protected TlsContext context; protected StreamCipher encryptCipher; @@ -21,13 +20,26 @@ public class TlsStreamCipher protected TlsMac writeMac; protected TlsMac readMac; + protected boolean usesNonce; + + /** + * @deprecated Use version with additional 'usesNonce' argument + */ public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher, StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest, int cipherKeySize) throws IOException + { + this(context, clientWriteCipher, serverWriteCipher, clientWriteDigest, serverWriteDigest, cipherKeySize, false); + } + + public TlsStreamCipher(TlsContext context, StreamCipher clientWriteCipher, + StreamCipher serverWriteCipher, Digest clientWriteDigest, Digest serverWriteDigest, + int cipherKeySize, boolean usesNonce) throws IOException { boolean isServer = context.isServer(); this.context = context; + this.usesNonce = usesNonce; this.encryptCipher = clientWriteCipher; this.decryptCipher = serverWriteCipher; @@ -78,6 +90,13 @@ public class TlsStreamCipher decryptParams = serverWriteKey; } + if (usesNonce) + { + byte[] dummyNonce = new byte[8]; + encryptParams = new ParametersWithIV(encryptParams, dummyNonce); + decryptParams = new ParametersWithIV(decryptParams, dummyNonce); + } + this.encryptCipher.init(true, encryptParams); this.decryptCipher.init(false, decryptParams); } @@ -90,26 +109,22 @@ public class TlsStreamCipher public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len) { /* - * TODO[draft-josefsson-salsa20-tls-02] Note that Salsa20 requires a 64-bit nonce. That + * draft-josefsson-salsa20-tls-04 2.1 Note that Salsa20 requires a 64-bit nonce. That * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation * of the 16-bit epoch with the 48-bit sequence number. */ + if (usesNonce) + { + updateIV(encryptCipher, true, seqNo); + } byte[] outBuf = new byte[len + writeMac.getSize()]; encryptCipher.processBytes(plaintext, offset, len, outBuf, 0); - if (encryptThenMAC) - { - byte[] mac = writeMac.calculateMac(seqNo, type, outBuf, 0, len); - System.arraycopy(mac, 0, outBuf, len, mac.length); - } - else - { - byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len); - encryptCipher.processBytes(mac, 0, mac.length, outBuf, len); - } + byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len); + encryptCipher.processBytes(mac, 0, mac.length, outBuf, len); return outBuf; } @@ -118,11 +133,15 @@ public class TlsStreamCipher throws IOException { /* - * TODO[draft-josefsson-salsa20-tls-02] Note that Salsa20 requires a 64-bit nonce. That + * draft-josefsson-salsa20-tls-04 2.1 Note that Salsa20 requires a 64-bit nonce. That * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation * of the 16-bit epoch with the 48-bit sequence number. */ + if (usesNonce) + { + updateIV(decryptCipher, false, seqNo); + } int macSize = readMac.getSize(); if (len < macSize) @@ -132,21 +151,10 @@ public class TlsStreamCipher int plaintextLength = len - macSize; - if (encryptThenMAC) - { - int ciphertextEnd = offset + len; - checkMAC(seqNo, type, ciphertext, ciphertextEnd - macSize, ciphertextEnd, ciphertext, offset, plaintextLength); - byte[] deciphered = new byte[plaintextLength]; - decryptCipher.processBytes(ciphertext, offset, plaintextLength, deciphered, 0); - return deciphered; - } - else - { - byte[] deciphered = new byte[len]; - decryptCipher.processBytes(ciphertext, offset, len, deciphered, 0); - checkMAC(seqNo, type, deciphered, plaintextLength, len, deciphered, 0, plaintextLength); - return Arrays.copyOfRange(deciphered, 0, plaintextLength); - } + byte[] deciphered = new byte[len]; + decryptCipher.processBytes(ciphertext, offset, len, deciphered, 0); + checkMAC(seqNo, type, deciphered, plaintextLength, len, deciphered, 0, plaintextLength); + return Arrays.copyOfRange(deciphered, 0, plaintextLength); } private void checkMAC(long seqNo, short type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen) @@ -160,4 +168,11 @@ public class TlsStreamCipher throw new TlsFatalAlert(AlertDescription.bad_record_mac); } } + + private void updateIV(StreamCipher cipher, boolean forEncryption, long seqNo) + { + byte[] nonce = new byte[8]; + TlsUtils.writeUint64(seqNo, nonce, 0); + cipher.init(forEncryption, new ParametersWithIV(null, nonce)); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java index 802db189d..118af480e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/TlsUtils.java @@ -43,7 +43,7 @@ import org.spongycastle.util.io.Streams; */ public class TlsUtils { - public static byte[] EMPTY_BYTES = new byte[0]; + public static final byte[] EMPTY_BYTES = new byte[0]; public static final Integer EXT_signature_algorithms = Integers.valueOf(ExtensionType.signature_algorithms); @@ -63,6 +63,14 @@ public class TlsUtils } } + public static void checkUint8(long i) throws IOException + { + if (!isValidUint8(i)) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + public static void checkUint16(int i) throws IOException { if (!isValidUint16(i)) @@ -71,6 +79,14 @@ public class TlsUtils } } + public static void checkUint16(long i) throws IOException + { + if (!isValidUint16(i)) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + public static void checkUint24(int i) throws IOException { if (!isValidUint24(i)) @@ -79,6 +95,14 @@ public class TlsUtils } } + public static void checkUint24(long i) throws IOException + { + if (!isValidUint24(i)) + { + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + public static void checkUint32(long i) throws IOException { if (!isValidUint32(i)) @@ -113,16 +137,31 @@ public class TlsUtils return (i & 0xFF) == i; } + public static boolean isValidUint8(long i) + { + return (i & 0xFFL) == i; + } + public static boolean isValidUint16(int i) { return (i & 0xFFFF) == i; } + public static boolean isValidUint16(long i) + { + return (i & 0xFFFFL) == i; + } + public static boolean isValidUint24(int i) { return (i & 0xFFFFFF) == i; } + public static boolean isValidUint24(long i) + { + return (i & 0xFFFFFFL) == i; + } + public static boolean isValidUint32(long i) { return (i & 0xFFFFFFFFL) == i; @@ -178,92 +217,92 @@ public class TlsUtils public static void writeUint16(int i, OutputStream output) throws IOException { - output.write(i >> 8); + output.write(i >>> 8); output.write(i); } public static void writeUint16(int i, byte[] buf, int offset) { - buf[offset] = (byte)(i >> 8); + buf[offset] = (byte)(i >>> 8); buf[offset + 1] = (byte)i; } public static void writeUint24(int i, OutputStream output) throws IOException { - output.write(i >> 16); - output.write(i >> 8); - output.write(i); + output.write((byte)(i >>> 16)); + output.write((byte)(i >>> 8)); + output.write((byte)i); } public static void writeUint24(int i, byte[] buf, int offset) { - buf[offset] = (byte)(i >> 16); - buf[offset + 1] = (byte)(i >> 8); - buf[offset + 2] = (byte)(i); + buf[offset] = (byte)(i >>> 16); + buf[offset + 1] = (byte)(i >>> 8); + buf[offset + 2] = (byte)i; } public static void writeUint32(long i, OutputStream output) throws IOException { - output.write((int)(i >> 24)); - output.write((int)(i >> 16)); - output.write((int)(i >> 8)); - output.write((int)(i)); + output.write((byte)(i >>> 24)); + output.write((byte)(i >>> 16)); + output.write((byte)(i >>> 8)); + output.write((byte)i); } public static void writeUint32(long i, byte[] buf, int offset) { - buf[offset] = (byte)(i >> 24); - buf[offset + 1] = (byte)(i >> 16); - buf[offset + 2] = (byte)(i >> 8); - buf[offset + 3] = (byte)(i); + buf[offset] = (byte)(i >>> 24); + buf[offset + 1] = (byte)(i >>> 16); + buf[offset + 2] = (byte)(i >>> 8); + buf[offset + 3] = (byte)i; } public static void writeUint48(long i, OutputStream output) throws IOException { - output.write((byte)(i >> 40)); - output.write((byte)(i >> 32)); - output.write((byte)(i >> 24)); - output.write((byte)(i >> 16)); - output.write((byte)(i >> 8)); - output.write((byte)(i)); + output.write((byte)(i >>> 40)); + output.write((byte)(i >>> 32)); + output.write((byte)(i >>> 24)); + output.write((byte)(i >>> 16)); + output.write((byte)(i >>> 8)); + output.write((byte)i); } public static void writeUint48(long i, byte[] buf, int offset) { - buf[offset] = (byte)(i >> 40); - buf[offset + 1] = (byte)(i >> 32); - buf[offset + 2] = (byte)(i >> 24); - buf[offset + 3] = (byte)(i >> 16); - buf[offset + 4] = (byte)(i >> 8); - buf[offset + 5] = (byte)(i); + buf[offset] = (byte)(i >>> 40); + buf[offset + 1] = (byte)(i >>> 32); + buf[offset + 2] = (byte)(i >>> 24); + buf[offset + 3] = (byte)(i >>> 16); + buf[offset + 4] = (byte)(i >>> 8); + buf[offset + 5] = (byte)i; } public static void writeUint64(long i, OutputStream output) throws IOException { - output.write((byte)(i >> 56)); - output.write((byte)(i >> 48)); - output.write((byte)(i >> 40)); - output.write((byte)(i >> 32)); - output.write((byte)(i >> 24)); - output.write((byte)(i >> 16)); - output.write((byte)(i >> 8)); - output.write((byte)(i)); + output.write((byte)(i >>> 56)); + output.write((byte)(i >>> 48)); + output.write((byte)(i >>> 40)); + output.write((byte)(i >>> 32)); + output.write((byte)(i >>> 24)); + output.write((byte)(i >>> 16)); + output.write((byte)(i >>> 8)); + output.write((byte)i); } public static void writeUint64(long i, byte[] buf, int offset) { - buf[offset] = (byte)(i >> 56); - buf[offset + 1] = (byte)(i >> 48); - buf[offset + 2] = (byte)(i >> 40); - buf[offset + 3] = (byte)(i >> 32); - buf[offset + 4] = (byte)(i >> 24); - buf[offset + 5] = (byte)(i >> 16); - buf[offset + 6] = (byte)(i >> 8); - buf[offset + 7] = (byte)(i); + buf[offset] = (byte)(i >>> 56); + buf[offset + 1] = (byte)(i >>> 48); + buf[offset + 2] = (byte)(i >>> 40); + buf[offset + 3] = (byte)(i >>> 32); + buf[offset + 4] = (byte)(i >>> 24); + buf[offset + 5] = (byte)(i >>> 16); + buf[offset + 6] = (byte)(i >>> 8); + buf[offset + 7] = (byte)i; } public static void writeOpaque8(byte[] buf, OutputStream output) @@ -451,23 +490,24 @@ public class TlsUtils { throw new EOFException(); } - return (((long)i1) << 24) | (((long)i2) << 16) | (((long)i3) << 8) | ((long)i4); + return ((i1 << 2) | (i2 << 16) | (i3 << 8) | i4) & 0xFFFFFFFFL; + } + + public static long readUint32(byte[] buf, int offset) + { + int n = (buf[offset] & 0xff) << 24; + n |= (buf[++offset] & 0xff) << 16; + n |= (buf[++offset] & 0xff) << 8; + n |= (buf[++offset] & 0xff); + return n & 0xFFFFFFFFL; } public static long readUint48(InputStream input) throws IOException { - int i1 = input.read(); - int i2 = input.read(); - int i3 = input.read(); - int i4 = input.read(); - int i5 = input.read(); - int i6 = input.read(); - if (i6 < 0) - { - throw new EOFException(); - } - return (((long)i1) << 40) | (((long)i2) << 32) | (((long)i3) << 24) | (((long)i4) << 16) | (((long)i5) << 8) | ((long)i6); + int hi = readUint24(input); + int lo = readUint24(input); + return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL); } public static long readUint48(byte[] buf, int offset) @@ -634,9 +674,9 @@ public class TlsUtils public static void writeGMTUnixTime(byte[] buf, int offset) { int t = (int)(System.currentTimeMillis() / 1000L); - buf[offset] = (byte)(t >> 24); - buf[offset + 1] = (byte)(t >> 16); - buf[offset + 2] = (byte)(t >> 8); + buf[offset] = (byte)(t >>> 24); + buf[offset + 1] = (byte)(t >>> 16); + buf[offset + 2] = (byte)(t >>> 8); buf[offset + 3] = (byte)t; } @@ -850,6 +890,14 @@ public class TlsUtils return buf; } + public static byte[] PRF_legacy(byte[] secret, String asciiLabel, byte[] seed, int size) + { + byte[] label = Strings.toByteArray(asciiLabel); + byte[] labelSeed = concat(label, seed); + + return PRF_legacy(secret, label, labelSeed, size); + } + static byte[] PRF_legacy(byte[] secret, byte[] label, byte[] labelSeed, int size) { int s_half = (secret.length + 1) / 2; @@ -860,8 +908,8 @@ public class TlsUtils byte[] b1 = new byte[size]; byte[] b2 = new byte[size]; - hmac_hash(new MD5Digest(), s1, labelSeed, b1); - hmac_hash(new SHA1Digest(), s2, labelSeed, b2); + hmac_hash(createHash(HashAlgorithm.md5), s1, labelSeed, b1); + hmac_hash(createHash(HashAlgorithm.sha1), s2, labelSeed, b2); for (int i = 0; i < size; i++) { b1[i] ^= b2[i]; @@ -880,7 +928,7 @@ public class TlsUtils static void hmac_hash(Digest digest, byte[] secret, byte[] seed, byte[] out) { HMac mac = new HMac(digest); - KeyParameter param = new KeyParameter(secret); + mac.init(new KeyParameter(secret)); byte[] a = seed; int size = digest.getDigestSize(); int iterations = (out.length + size - 1) / size; @@ -888,11 +936,9 @@ public class TlsUtils byte[] buf2 = new byte[mac.getMacSize()]; for (int i = 0; i < iterations; i++) { - mac.init(param); mac.update(a, 0, a.length); mac.doFinal(buf, 0); a = buf; - mac.init(param); mac.update(a, 0, a.length); mac.update(seed, 0, seed.length); mac.doFinal(buf2, 0); @@ -935,8 +981,8 @@ public class TlsUtils static byte[] calculateKeyBlock_SSL(byte[] master_secret, byte[] random, int size) { - Digest md5 = new MD5Digest(); - Digest sha1 = new SHA1Digest(); + Digest md5 = createHash(HashAlgorithm.md5); + Digest sha1 = createHash(HashAlgorithm.sha1); int md5Size = md5.getDigestSize(); byte[] shatmp = new byte[sha1.getDigestSize()]; byte[] tmp = new byte[size + md5Size]; @@ -979,8 +1025,8 @@ public class TlsUtils static byte[] calculateMasterSecret_SSL(byte[] pre_master_secret, byte[] random) { - Digest md5 = new MD5Digest(); - Digest sha1 = new SHA1Digest(); + Digest md5 = createHash(HashAlgorithm.md5); + Digest sha1 = createHash(HashAlgorithm.sha1); int md5Size = md5.getDigestSize(); byte[] shatmp = new byte[sha1.getDigestSize()]; @@ -1020,7 +1066,7 @@ public class TlsUtils return PRF(context, master_secret, asciiLabel, handshakeHash, verify_data_length); } - public static final Digest createHash(short hashAlgorithm) + public static Digest createHash(short hashAlgorithm) { switch (hashAlgorithm) { @@ -1041,7 +1087,7 @@ public class TlsUtils } } - public static final Digest cloneHash(short hashAlgorithm, Digest hash) + public static Digest cloneHash(short hashAlgorithm, Digest hash) { switch (hashAlgorithm) { @@ -1062,7 +1108,7 @@ public class TlsUtils } } - public static final Digest createPRFHash(int prfAlgorithm) + public static Digest createPRFHash(int prfAlgorithm) { switch (prfAlgorithm) { @@ -1073,7 +1119,7 @@ public class TlsUtils } } - public static final Digest clonePRFHash(int prfAlgorithm, Digest hash) + public static Digest clonePRFHash(int prfAlgorithm, Digest hash) { switch (prfAlgorithm) { @@ -1084,7 +1130,7 @@ public class TlsUtils } } - public static final short getHashAlgorithmForPRFAlgorithm(int prfAlgorithm) + public static short getHashAlgorithmForPRFAlgorithm(int prfAlgorithm) { switch (prfAlgorithm) { @@ -1258,4 +1304,477 @@ public class TlsUtils v.addElement(obj); return v; } + + public static int getCipherType(int ciphersuite) throws IOException + { + switch (getEncryptionAlgorithm(ciphersuite)) + { + case EncryptionAlgorithm.AES_128_GCM: + case EncryptionAlgorithm.AES_256_GCM: + case EncryptionAlgorithm.AES_128_CCM: + case EncryptionAlgorithm.AES_128_CCM_8: + case EncryptionAlgorithm.AES_256_CCM: + case EncryptionAlgorithm.AES_256_CCM_8: + case EncryptionAlgorithm.CAMELLIA_128_GCM: + case EncryptionAlgorithm.CAMELLIA_256_GCM: + case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305: + return CipherType.aead; + + case EncryptionAlgorithm.RC2_CBC_40: + case EncryptionAlgorithm.IDEA_CBC: + case EncryptionAlgorithm.DES40_CBC: + case EncryptionAlgorithm.DES_CBC: + case EncryptionAlgorithm._3DES_EDE_CBC: + case EncryptionAlgorithm.AES_128_CBC: + case EncryptionAlgorithm.AES_256_CBC: + case EncryptionAlgorithm.CAMELLIA_128_CBC: + case EncryptionAlgorithm.CAMELLIA_256_CBC: + case EncryptionAlgorithm.SEED_CBC: + return CipherType.block; + + case EncryptionAlgorithm.RC4_40: + case EncryptionAlgorithm.RC4_128: + case EncryptionAlgorithm.ESTREAM_SALSA20: + case EncryptionAlgorithm.SALSA20: + return CipherType.stream; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public static int getEncryptionAlgorithm(int ciphersuite) throws IOException + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA: + return EncryptionAlgorithm._3DES_EDE_CBC; + + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + return EncryptionAlgorithm.AEAD_CHACHA20_POLY1305; + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA: + return EncryptionAlgorithm.AES_128_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + return EncryptionAlgorithm.AES_128_CBC; + + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + return EncryptionAlgorithm.AES_128_CCM; + + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + return EncryptionAlgorithm.AES_128_CCM_8; + + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + return EncryptionAlgorithm.AES_128_GCM; + + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: + case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA: + return EncryptionAlgorithm.AES_256_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + return EncryptionAlgorithm.AES_256_CBC; + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: + return EncryptionAlgorithm.AES_256_CBC; + + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + return EncryptionAlgorithm.AES_256_CCM; + + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + return EncryptionAlgorithm.AES_256_CCM_8; + + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + return EncryptionAlgorithm.AES_256_GCM; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA: + return EncryptionAlgorithm.CAMELLIA_128_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + return EncryptionAlgorithm.CAMELLIA_128_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + return EncryptionAlgorithm.CAMELLIA_128_GCM; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA: + return EncryptionAlgorithm.CAMELLIA_256_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + return EncryptionAlgorithm.CAMELLIA_256_CBC; + + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: + return EncryptionAlgorithm.CAMELLIA_256_CBC; + + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + return EncryptionAlgorithm.CAMELLIA_256_GCM; + + case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1: + return EncryptionAlgorithm.ESTREAM_SALSA20; + + case CipherSuite.TLS_RSA_WITH_NULL_MD5: + return EncryptionAlgorithm.NULL; + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA: + case CipherSuite.TLS_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA: + case CipherSuite.TLS_RSA_WITH_NULL_SHA: + return EncryptionAlgorithm.NULL; + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + return EncryptionAlgorithm.NULL; + + case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_PSK_WITH_NULL_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384: + return EncryptionAlgorithm.NULL; + + case CipherSuite.TLS_DH_anon_WITH_RC4_128_MD5: + case CipherSuite.TLS_RSA_WITH_RC4_128_MD5: + return EncryptionAlgorithm.RC4_128; + + case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_PSK_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_WITH_RC4_128_SHA: + case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA: + return EncryptionAlgorithm.RC4_128; + + case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1: + case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1: + case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1: + return EncryptionAlgorithm.SALSA20; + + case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA: + case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA: + return EncryptionAlgorithm.SEED_CBC; + + default: + throw new TlsFatalAlert(AlertDescription.internal_error); + } + } + + public static ProtocolVersion getMinimumVersion(int ciphersuite) + { + switch (ciphersuite) + { + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM: + case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM: + case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8: + case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM: + case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM: + case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8: + case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256: + case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384: + case CipherSuite.TLS_RSA_WITH_NULL_SHA256: + return ProtocolVersion.TLSv12; + + default: + return ProtocolVersion.SSLv3; + } + } + + public static boolean isAEADCipherSuite(int ciphersuite) throws IOException + { + return CipherType.aead == getCipherType(ciphersuite); + } + + public static boolean isBlockCipherSuite(int ciphersuite) throws IOException + { + return CipherType.block == getCipherType(ciphersuite); + } + + public static boolean isStreamCipherSuite(int ciphersuite) throws IOException + { + return CipherType.stream == getCipherType(ciphersuite); + } + + public static boolean isValidCipherSuiteForVersion(int cipherSuite, ProtocolVersion serverVersion) + { + return getMinimumVersion(cipherSuite).isEqualOrEarlierVersionOf(serverVersion.getEquivalentTLSVersion()); + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java index 4c1c33e9c..8202dd1e6 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/tls/UseSRTPData.java @@ -5,7 +5,6 @@ package org.spongycastle.crypto.tls; */ public class UseSRTPData { - private int[] protectionProfiles; private byte[] mki; @@ -15,7 +14,6 @@ public class UseSRTPData */ public UseSRTPData(int[] protectionProfiles, byte[] mki) { - if (protectionProfiles == null || protectionProfiles.length < 1 || protectionProfiles.length >= (1 << 15)) { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/Pack.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/Pack.java index 7b12eb4a5..e7743e9a9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/Pack.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/Pack.java @@ -1,5 +1,8 @@ package org.spongycastle.crypto.util; +/** + * @deprecated use org.spongycastle.util.pack + */ public abstract class Pack { public static int bigEndianToInt(byte[] bs, int off) @@ -114,6 +117,15 @@ public abstract class Pack } } + public static void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) + { + for (int i = 0; i < count; ++i) + { + ns[nOff + i] = littleEndianToInt(bs, bOff); + bOff += 4; + } + } + public static byte[] intToLittleEndian(int n) { byte[] bs = new byte[4]; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java index 750c6ac55..289b25f5e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyFactory.java @@ -9,7 +9,6 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.pkcs.DHParameter; @@ -23,12 +22,14 @@ import org.spongycastle.asn1.x9.ECNamedCurveTable; import org.spongycastle.asn1.x9.X962Parameters; import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.ec.CustomNamedCurves; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.DHParameters; import org.spongycastle.crypto.params.DHPrivateKeyParameters; import org.spongycastle.crypto.params.DSAParameters; import org.spongycastle.crypto.params.DSAPrivateKeyParameters; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ElGamalParameters; import org.spongycastle.crypto.params.ElGamalPrivateKeyParameters; @@ -99,7 +100,7 @@ public class PrivateKeyFactory } else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters()); + ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters( @@ -124,24 +125,30 @@ public class PrivateKeyFactory X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters()); X9ECParameters x9; + ECDomainParameters dParams; + if (params.isNamedCurve()) { - ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); - x9 = ECNamedCurveTable.getByOID(oid); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + + x9 = CustomNamedCurves.getByOID(oid); + if (x9 == null) + { + x9 = ECNamedCurveTable.getByOID(oid); + } + dParams = new ECNamedDomainParameters( + oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); } else { x9 = X9ECParameters.getInstance(params.getParameters()); + dParams = new ECDomainParameters( + x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); } ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey()); BigInteger d = ec.getKey(); - // TODO We lose any named parameters here - - ECDomainParameters dParams = new ECDomainParameters( - x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); - return new ECPrivateKeyParameters(d, dParams); } else diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java index 49cdcaa81..3fa6d2f15 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PrivateKeyInfoFactory.java @@ -18,6 +18,7 @@ import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.DSAParameters; import org.spongycastle.crypto.params.DSAPrivateKeyParameters; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.RSAKeyParameters; import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; @@ -55,11 +56,14 @@ public class PrivateKeyInfoFactory ECDomainParameters domainParams = priv.getParameters(); ASN1Encodable params; - // TODO: need to handle named curves if (domainParams == null) { params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA } + else if (domainParams instanceof ECNamedDomainParameters) + { + params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + } else { X9ECParameters ecP = new X9ECParameters( diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java index aaa4e412d..ec588f46a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/PublicKeyFactory.java @@ -10,7 +10,6 @@ import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -29,6 +28,7 @@ import org.spongycastle.asn1.x9.X962Parameters; import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ECPoint; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.ec.CustomNamedCurves; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.DHParameters; import org.spongycastle.crypto.params.DHPublicKeyParameters; @@ -36,6 +36,7 @@ import org.spongycastle.crypto.params.DHValidationParameters; import org.spongycastle.crypto.params.DSAParameters; import org.spongycastle.crypto.params.DSAPublicKeyParameters; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ElGamalParameters; import org.spongycastle.crypto.params.ElGamalPublicKeyParameters; @@ -134,7 +135,7 @@ public class PublicKeyFactory } else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm)) { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters()); + ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters( @@ -160,24 +161,30 @@ public class PublicKeyFactory X962Parameters params = X962Parameters.getInstance(algId.getParameters()); X9ECParameters x9; + ECDomainParameters dParams; + if (params.isNamedCurve()) { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); - x9 = ECNamedCurveTable.getByOID(oid); + + x9 = CustomNamedCurves.getByOID(oid); + if (x9 == null) + { + x9 = ECNamedCurveTable.getByOID(oid); + } + dParams = new ECNamedDomainParameters( + oid, x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); } else { x9 = X9ECParameters.getInstance(params.getParameters()); + dParams = new ECDomainParameters( + x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); } ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes()); X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key); - // TODO We lose any named parameters here - - ECDomainParameters dParams = new ECDomainParameters( - x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); - return new ECPublicKeyParameters(derQ.getPoint(), dParams); } else diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java index 131ba445f..749de7f3a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/crypto/util/SubjectPublicKeyInfoFactory.java @@ -17,6 +17,7 @@ import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.DSAPublicKeyParameters; import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECNamedDomainParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.RSAKeyParameters; @@ -52,11 +53,14 @@ public class SubjectPublicKeyInfoFactory ECDomainParameters domainParams = pub.getParameters(); ASN1Encodable params; - // TODO: need to handle named curves if (domainParams == null) { params = new X962Parameters(DERNull.INSTANCE); // Implicitly CA } + else if (domainParams instanceof ECNamedDomainParameters) + { + params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + } else { X9ECParameters ecP = new X9ECParameters( diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java index 93de81c9f..e4dee6dd2 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/AbstractECMultiplier.java @@ -13,7 +13,13 @@ public abstract class AbstractECMultiplier implements ECMultiplier } ECPoint positive = multiplyPositive(p, k.abs()); - return sign > 0 ? positive : positive.negate(); + ECPoint result = sign > 0 ? positive : positive.negate(); + + /* + * Although the various multipliers ought not to produce invalid output under normal + * circumstances, a final check here is advised to guard against fault attacks. + */ + return ECAlgorithms.validatePoint(result); } protected abstract ECPoint multiplyPositive(ECPoint p, BigInteger k); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java index a1e923e51..7d73cebee 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECAlgorithms.java @@ -2,8 +2,62 @@ package org.spongycastle.math.ec; import java.math.BigInteger; +import org.spongycastle.math.ec.endo.ECEndomorphism; +import org.spongycastle.math.ec.endo.GLVEndomorphism; +import org.spongycastle.math.field.FiniteField; +import org.spongycastle.math.field.PolynomialExtensionField; + public class ECAlgorithms { + public static boolean isF2mCurve(ECCurve c) + { + FiniteField field = c.getField(); + return field.getDimension() > 1 && field.getCharacteristic().equals(ECConstants.TWO) + && field instanceof PolynomialExtensionField; + } + + public static boolean isFpCurve(ECCurve c) + { + return c.getField().getDimension() == 1; + } + + public static ECPoint sumOfMultiplies(ECPoint[] ps, BigInteger[] ks) + { + if (ps == null || ks == null || ps.length != ks.length || ps.length < 1) + { + throw new IllegalArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length"); + } + + int count = ps.length; + switch (count) + { + case 1: + return ps[0].multiply(ks[0]); + case 2: + return sumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]); + default: + break; + } + + ECPoint p = ps[0]; + ECCurve c = p.getCurve(); + + ECPoint[] imported = new ECPoint[count]; + imported[0] = p; + for (int i = 1; i < count; ++i) + { + imported[i] = importPoint(c, ps[i]); + } + + ECEndomorphism endomorphism = c.getEndomorphism(); + if (endomorphism instanceof GLVEndomorphism) + { + return validatePoint(implSumOfMultipliesGLV(imported, ks, (GLVEndomorphism)endomorphism)); + } + + return validatePoint(implSumOfMultiplies(imported, ks)); + } + public static ECPoint sumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b) { @@ -16,11 +70,18 @@ public class ECAlgorithms ECCurve.F2m f2mCurve = (ECCurve.F2m)cp; if (f2mCurve.isKoblitz()) { - return P.multiply(a).add(Q.multiply(b)); + return validatePoint(P.multiply(a).add(Q.multiply(b))); } } - return implShamirsTrick(P, a, Q, b); + ECEndomorphism endomorphism = cp.getEndomorphism(); + if (endomorphism instanceof GLVEndomorphism) + { + return validatePoint( + implSumOfMultipliesGLV(new ECPoint[]{ P, Q }, new BigInteger[]{ a, b }, (GLVEndomorphism)endomorphism)); + } + + return validatePoint(implShamirsTrickWNaf(P, a, Q, b)); } /* @@ -48,7 +109,7 @@ public class ECAlgorithms ECCurve cp = P.getCurve(); Q = importPoint(cp, Q); - return implShamirsTrick(P, k, Q, l); + return validatePoint(implShamirsTrickJsf(P, k, Q, l)); } public static ECPoint importPoint(ECCurve c, ECPoint p) @@ -61,7 +122,7 @@ public class ECAlgorithms return c.importPoint(p); } - static void implMontgomeryTrick(ECFieldElement[] zs, int off, int len) + public static void montgomeryTrick(ECFieldElement[] zs, int off, int len) { /* * Uses the "Montgomery Trick" to invert many field elements, with only a single actual @@ -92,7 +153,50 @@ public class ECAlgorithms zs[off] = u; } - static ECPoint implShamirsTrick(ECPoint P, BigInteger k, + /** + * Simple shift-and-add multiplication. Serves as reference implementation + * to verify (possibly faster) implementations, and for very small scalars. + * + * @param p + * The point to multiply. + * @param k + * The multiplier. + * @return The result of the point multiplication
*kP
. + */ + public static ECPoint referenceMultiply(ECPoint p, BigInteger k) + { + BigInteger x = k.abs(); + ECPoint q = p.getCurve().getInfinity(); + int t = x.bitLength(); + if (t > 0) + { + if (x.testBit(0)) + { + q = p; + } + for (int i = 1; i < t; i++) + { + p = p.twice(); + if (x.testBit(i)) + { + q = q.add(p); + } + } + } + return k.signum() < 0 ? q.negate() : q; + } + + public static ECPoint validatePoint(ECPoint p) + { + if (!p.isValid()) + { + throw new IllegalArgumentException("Invalid point"); + } + + return p; + } + + static ECPoint implShamirsTrickJsf(ECPoint P, BigInteger k, ECPoint Q, BigInteger l) { ECCurve curve = P.getCurve(); @@ -118,7 +222,9 @@ public class ECAlgorithms while (--i >= 0) { int jsfi = jsf[i]; - int kDigit = (jsfi >> 4), lDigit = ((jsfi << 28) >> 28); + + // NOTE: The shifting ensures the sign is extended correctly + int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28); int index = 4 + (kDigit * 3) + lDigit; R = R.twicePlus(table[index]); @@ -126,4 +232,238 @@ public class ECAlgorithms return R; } + + static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k, + ECPoint Q, BigInteger l) + { + boolean negK = k.signum() < 0, negL = l.signum() < 0; + + k = k.abs(); + l = l.abs(); + + int widthP = Math.max(2, Math.min(16, WNafUtil.getWindowSize(k.bitLength()))); + int widthQ = Math.max(2, Math.min(16, WNafUtil.getWindowSize(l.bitLength()))); + + WNafPreCompInfo infoP = WNafUtil.precompute(P, widthP, true); + WNafPreCompInfo infoQ = WNafUtil.precompute(Q, widthQ, true); + + ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp(); + ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp(); + ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg(); + ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg(); + + byte[] wnafP = WNafUtil.generateWindowNaf(widthP, k); + byte[] wnafQ = WNafUtil.generateWindowNaf(widthQ, l); + + return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ); + } + + static ECPoint implShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l) + { + boolean negK = k.signum() < 0, negL = l.signum() < 0; + + k = k.abs(); + l = l.abs(); + + int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(k.bitLength(), l.bitLength())))); + + ECPoint Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMapQ); + WNafPreCompInfo infoP = WNafUtil.getWNafPreCompInfo(P); + WNafPreCompInfo infoQ = WNafUtil.getWNafPreCompInfo(Q); + + ECPoint[] preCompP = negK ? infoP.getPreCompNeg() : infoP.getPreComp(); + ECPoint[] preCompQ = negL ? infoQ.getPreCompNeg() : infoQ.getPreComp(); + ECPoint[] preCompNegP = negK ? infoP.getPreComp() : infoP.getPreCompNeg(); + ECPoint[] preCompNegQ = negL ? infoQ.getPreComp() : infoQ.getPreCompNeg(); + + byte[] wnafP = WNafUtil.generateWindowNaf(width, k); + byte[] wnafQ = WNafUtil.generateWindowNaf(width, l); + + return implShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ); + } + + private static ECPoint implShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP, + ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ) + { + int len = Math.max(wnafP.length, wnafQ.length); + + ECCurve curve = preCompP[0].getCurve(); + ECPoint infinity = curve.getInfinity(); + + ECPoint R = infinity; + int zeroes = 0; + + for (int i = len - 1; i >= 0; --i) + { + int wiP = i < wnafP.length ? wnafP[i] : 0; + int wiQ = i < wnafQ.length ? wnafQ[i] : 0; + + if ((wiP | wiQ) == 0) + { + ++zeroes; + continue; + } + + ECPoint r = infinity; + if (wiP != 0) + { + int nP = Math.abs(wiP); + ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP; + r = r.add(tableP[nP >>> 1]); + } + if (wiQ != 0) + { + int nQ = Math.abs(wiQ); + ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ; + r = r.add(tableQ[nQ >>> 1]); + } + + if (zeroes > 0) + { + R = R.timesPow2(zeroes); + zeroes = 0; + } + + R = R.twicePlus(r); + } + + if (zeroes > 0) + { + R = R.timesPow2(zeroes); + } + + return R; + } + + static ECPoint implSumOfMultiplies(ECPoint[] ps, BigInteger[] ks) + { + int count = ps.length; + boolean[] negs = new boolean[count]; + WNafPreCompInfo[] infos = new WNafPreCompInfo[count]; + byte[][] wnafs = new byte[count][]; + + for (int i = 0; i < count; ++i) + { + BigInteger ki = ks[i]; negs[i] = ki.signum() < 0; ki = ki.abs(); + + int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(ki.bitLength()))); + infos[i] = WNafUtil.precompute(ps[i], width, true); + wnafs[i] = WNafUtil.generateWindowNaf(width, ki); + } + + return implSumOfMultiplies(negs, infos, wnafs); + } + + static ECPoint implSumOfMultipliesGLV(ECPoint[] ps, BigInteger[] ks, GLVEndomorphism glvEndomorphism) + { + BigInteger n = ps[0].getCurve().getOrder(); + + int len = ps.length; + + BigInteger[] abs = new BigInteger[len << 1]; + for (int i = 0, j = 0; i < len; ++i) + { + BigInteger[] ab = glvEndomorphism.decomposeScalar(ks[i].mod(n)); + abs[j++] = ab[0]; + abs[j++] = ab[1]; + } + + ECPointMap pointMap = glvEndomorphism.getPointMap(); + if (glvEndomorphism.hasEfficientPointMap()) + { + return ECAlgorithms.implSumOfMultiplies(ps, pointMap, abs); + } + + ECPoint[] pqs = new ECPoint[len << 1]; + for (int i = 0, j = 0; i < len; ++i) + { + ECPoint p = ps[i], q = pointMap.map(p); + pqs[j++] = p; + pqs[j++] = q; + } + + return ECAlgorithms.implSumOfMultiplies(pqs, abs); + + } + + static ECPoint implSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks) + { + int halfCount = ps.length, fullCount = halfCount << 1; + + boolean[] negs = new boolean[fullCount]; + WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount]; + byte[][] wnafs = new byte[fullCount][]; + + for (int i = 0; i < halfCount; ++i) + { + int j0 = i << 1, j1 = j0 + 1; + + BigInteger kj0 = ks[j0]; negs[j0] = kj0.signum() < 0; kj0 = kj0.abs(); + BigInteger kj1 = ks[j1]; negs[j1] = kj1.signum() < 0; kj1 = kj1.abs(); + + int width = Math.max(2, Math.min(16, WNafUtil.getWindowSize(Math.max(kj0.bitLength(), kj1.bitLength())))); + + ECPoint P = ps[i], Q = WNafUtil.mapPointWithPrecomp(P, width, true, pointMap); + infos[j0] = WNafUtil.getWNafPreCompInfo(P); + infos[j1] = WNafUtil.getWNafPreCompInfo(Q); + wnafs[j0] = WNafUtil.generateWindowNaf(width, kj0); + wnafs[j1] = WNafUtil.generateWindowNaf(width, kj1); + } + + return implSumOfMultiplies(negs, infos, wnafs); + } + + private static ECPoint implSumOfMultiplies(boolean[] negs, WNafPreCompInfo[] infos, byte[][] wnafs) + { + int len = 0, count = wnafs.length; + for (int i = 0; i < count; ++i) + { + len = Math.max(len, wnafs[i].length); + } + + ECCurve curve = infos[0].getPreComp()[0].getCurve(); + ECPoint infinity = curve.getInfinity(); + + ECPoint R = infinity; + int zeroes = 0; + + for (int i = len - 1; i >= 0; --i) + { + ECPoint r = infinity; + + for (int j = 0; j < count; ++j) + { + byte[] wnaf = wnafs[j]; + int wi = i < wnaf.length ? wnaf[i] : 0; + if (wi != 0) + { + int n = Math.abs(wi); + WNafPreCompInfo info = infos[j]; + ECPoint[] table = (wi < 0 == negs[j]) ? info.getPreComp() : info.getPreCompNeg(); + r = r.add(table[n >>> 1]); + } + } + + if (r == infinity) + { + ++zeroes; + continue; + } + + if (zeroes > 0) + { + R = R.timesPow2(zeroes); + zeroes = 0; + } + + R = R.twicePlus(r); + } + + if (zeroes > 0) + { + R = R.timesPow2(zeroes); + } + + return R; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECCurve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECCurve.java index 137681e3b..35c354735 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECCurve.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECCurve.java @@ -1,9 +1,15 @@ package org.spongycastle.math.ec; import java.math.BigInteger; +import java.util.Hashtable; import java.util.Random; +import org.spongycastle.math.ec.endo.ECEndomorphism; +import org.spongycastle.math.ec.endo.GLVEndomorphism; +import org.spongycastle.math.field.FiniteField; +import org.spongycastle.math.field.FiniteFields; import org.spongycastle.util.BigIntegers; +import org.spongycastle.util.Integers; /** * base class for an elliptic curve @@ -28,11 +34,13 @@ public abstract class ECCurve public class Config { protected int coord; + protected ECEndomorphism endomorphism; protected ECMultiplier multiplier; - Config(int coord, ECMultiplier multiplier) + Config(int coord, ECEndomorphism endomorphism, ECMultiplier multiplier) { this.coord = coord; + this.endomorphism = endomorphism; this.multiplier = multiplier; } @@ -42,6 +50,12 @@ public abstract class ECCurve return this; } + public Config setEndomorphism(ECEndomorphism endomorphism) + { + this.endomorphism = endomorphism; + return this; + } + public Config setMultiplier(ECMultiplier multiplier) { this.multiplier = multiplier; @@ -62,23 +76,57 @@ public abstract class ECCurve } c.coord = coord; + c.endomorphism = endomorphism; c.multiplier = multiplier; return c; } } + protected FiniteField field; protected ECFieldElement a, b; + protected BigInteger order, cofactor; + protected int coord = COORD_AFFINE; + protected ECEndomorphism endomorphism = null; protected ECMultiplier multiplier = null; + protected ECCurve(FiniteField field) + { + this.field = field; + } + public abstract int getFieldSize(); public abstract ECFieldElement fromBigInteger(BigInteger x); public Config configure() { - return new Config(this.coord, this.multiplier); + return new Config(this.coord, this.endomorphism, this.multiplier); + } + + public ECPoint validatePoint(BigInteger x, BigInteger y) + { + ECPoint p = createPoint(x, y); + if (!p.isValid()) + { + throw new IllegalArgumentException("Invalid point coordinates"); + } + return p; + } + + /** + * @deprecated per-point compression property will be removed, use {@link #validatePoint(BigInteger, BigInteger)} + * and refer {@link ECPoint#getEncoded(boolean)} + */ + public ECPoint validatePoint(BigInteger x, BigInteger y, boolean withCompression) + { + ECPoint p = createPoint(x, y, withCompression); + if (!p.isValid()) + { + throw new IllegalArgumentException("Invalid point coordinates"); + } + return p; } public ECPoint createPoint(BigInteger x, BigInteger y) @@ -99,8 +147,15 @@ public abstract class ECCurve protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression); + protected abstract ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression); + protected ECMultiplier createDefaultMultiplier() { + if (endomorphism instanceof GLVEndomorphism) + { + return new GLVMultiplier(this, (GLVEndomorphism)endomorphism); + } + return new WNafL2RMultiplier(); } @@ -109,26 +164,40 @@ public abstract class ECCurve return coord == COORD_AFFINE; } - public PreCompInfo getPreCompInfo(ECPoint p) + public PreCompInfo getPreCompInfo(ECPoint point, String name) { - checkPoint(p); - return p.preCompInfo; + checkPoint(point); + synchronized (point) + { + Hashtable table = point.preCompTable; + return table == null ? null : (PreCompInfo)table.get(name); + } } /** - * Sets thePreCompInfo
for a point on this curve. Used by + * AddsPreCompInfo
for a point on this curve, under a given name. Used by *ECMultiplier
s to save the precomputation for thisECPoint
for use * by subsequent multiplication. * * @param point * TheECPoint
to store precomputations for. + * @param name + * AString
used to index precomputations of different types. * @param preCompInfo * The values precomputed by theECMultiplier
. */ - public void setPreCompInfo(ECPoint point, PreCompInfo preCompInfo) + public void setPreCompInfo(ECPoint point, String name, PreCompInfo preCompInfo) { checkPoint(point); - point.preCompInfo = preCompInfo; + synchronized (point) + { + Hashtable table = point.preCompTable; + if (null == table) + { + point.preCompTable = table = new Hashtable(4); + } + table.put(name, preCompInfo); + } } public ECPoint importPoint(ECPoint p) @@ -145,7 +214,7 @@ public abstract class ECCurve // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates. p = p.normalize(); - return createPoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression); + return validatePoint(p.getXCoord().toBigInteger(), p.getYCoord().toBigInteger(), p.withCompression); } /** @@ -188,7 +257,7 @@ public abstract class ECCurve return; } - ECAlgorithms.implMontgomeryTrick(zs, 0, count); + ECAlgorithms.montgomeryTrick(zs, 0, count); for (int j = 0; j < count; ++j) { @@ -199,6 +268,11 @@ public abstract class ECCurve public abstract ECPoint getInfinity(); + public FiniteField getField() + { + return field; + } + public ECFieldElement getA() { return a; @@ -209,6 +283,16 @@ public abstract class ECCurve return b; } + public BigInteger getOrder() + { + return order; + } + + public BigInteger getCofactor() + { + return cofactor; + } + public int getCoordinateSystem() { return coord; @@ -216,10 +300,15 @@ public abstract class ECCurve protected abstract ECPoint decompressPoint(int yTilde, BigInteger X1); + public ECEndomorphism getEndomorphism() + { + return endomorphism; + } + /** * Sets the defaultECMultiplier
, unless already set. */ - public ECMultiplier getMultiplier() + public synchronized ECMultiplier getMultiplier() { if (this.multiplier == null) { @@ -239,7 +328,8 @@ public abstract class ECCurve ECPoint p = null; int expectedLength = (getFieldSize() + 7) / 8; - switch (encoded[0]) + byte type = encoded[0]; + switch (type) { case 0x00: // infinity { @@ -259,29 +349,56 @@ public abstract class ECCurve throw new IllegalArgumentException("Incorrect length for compressed encoding"); } - int yTilde = encoded[0] & 1; + int yTilde = type & 1; BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); p = decompressPoint(yTilde, X); + if (!p.satisfiesCofactor()) + { + throw new IllegalArgumentException("Invalid point"); + } + break; } case 0x04: // uncompressed - case 0x06: // hybrid - case 0x07: // hybrid { if (encoded.length != (2 * expectedLength + 1)) { - throw new IllegalArgumentException("Incorrect length for uncompressed/hybrid encoding"); + throw new IllegalArgumentException("Incorrect length for uncompressed encoding"); } BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength); - p = createPoint(X, Y); + p = validatePoint(X, Y); + break; + } + case 0x06: // hybrid + case 0x07: // hybrid + { + if (encoded.length != (2 * expectedLength + 1)) + { + throw new IllegalArgumentException("Incorrect length for hybrid encoding"); + } + + BigInteger X = BigIntegers.fromUnsignedByteArray(encoded, 1, expectedLength); + BigInteger Y = BigIntegers.fromUnsignedByteArray(encoded, 1 + expectedLength, expectedLength); + + if (Y.testBit(0) != (type == 0x07)) + { + throw new IllegalArgumentException("Inconsistent Y coordinate in hybrid encoding"); + } + + p = validatePoint(X, Y); break; } default: - throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); + throw new IllegalArgumentException("Invalid point encoding 0x" + Integer.toString(type, 16)); + } + + if (type != 0x00 && p.isInfinity()) + { + throw new IllegalArgumentException("Invalid infinity encoding"); } return p; @@ -312,10 +429,62 @@ public abstract class ECCurve } } + public boolean equals(ECCurve other) + { + return this == other + || (null != other + && getField().equals(other.getField()) + && getA().toBigInteger().equals(other.getA().toBigInteger()) + && getB().toBigInteger().equals(other.getB().toBigInteger())); + } + + public boolean equals(Object obj) + { + return this == obj || (obj instanceof ECCurve && equals((ECCurve)obj)); + } + + public int hashCode() + { + return getField().hashCode() + ^ Integers.rotateLeft(getA().toBigInteger().hashCode(), 8) + ^ Integers.rotateLeft(getB().toBigInteger().hashCode(), 16); + } + + public static abstract class AbstractFp extends ECCurve + { + protected AbstractFp(BigInteger q) + { + super(FiniteFields.getPrimeField(q)); + } + + protected ECPoint decompressPoint(int yTilde, BigInteger X1) + { + ECFieldElement x = this.fromBigInteger(X1); + ECFieldElement rhs = x.square().add(a).multiply(x).add(b); + ECFieldElement y = rhs.sqrt(); + + /* + * If y is not a square, then we haven't got a point on the curve + */ + if (y == null) + { + throw new IllegalArgumentException("Invalid point compression"); + } + + if (y.testBitZero() != (yTilde == 1)) + { + // Use the other root + y = y.negate(); + } + + return this.createRawPoint(x, y, true); + } + } + /** * Elliptic curve over Fp */ - public static class Fp extends ECCurve + public static class Fp extends AbstractFp { private static final int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; @@ -324,29 +493,47 @@ public abstract class ECCurve public Fp(BigInteger q, BigInteger a, BigInteger b) { + this(q, a, b, null, null); + } + + public Fp(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor) + { + super(q); + this.q = q; this.r = ECFieldElement.Fp.calculateResidue(q); this.infinity = new ECPoint.Fp(this, null, null); this.a = fromBigInteger(a); this.b = fromBigInteger(b); + this.order = order; + this.cofactor = cofactor; this.coord = FP_DEFAULT_COORDS; } protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b) { + this(q, r, a, b, null, null); + } + + protected Fp(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) + { + super(q); + this.q = q; this.r = r; this.infinity = new ECPoint.Fp(this, null, null); this.a = a; this.b = b; + this.order = order; + this.cofactor = cofactor; this.coord = FP_DEFAULT_COORDS; } protected ECCurve cloneCurve() { - return new Fp(q, r, a, b); + return new Fp(q, r, a, b, order, cofactor); } public boolean supportsCoordinateSystem(int coord) @@ -383,6 +570,11 @@ public abstract class ECCurve return new ECPoint.Fp(this, x, y, withCompression); } + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new ECPoint.Fp(this, x, y, zs, withCompression); + } + public ECPoint importPoint(ECPoint p) { if (this != p.getCurve() && this.getCoordinateSystem() == COORD_JACOBIAN && !p.isInfinity()) @@ -405,58 +597,47 @@ public abstract class ECCurve return super.importPoint(p); } - protected ECPoint decompressPoint(int yTilde, BigInteger X1) - { - ECFieldElement x = fromBigInteger(X1); - ECFieldElement alpha = x.multiply(x.square().add(a)).add(b); - ECFieldElement beta = alpha.sqrt(); - - // - // if we can't find a sqrt we haven't got a point on the - // curve - run! - // - if (beta == null) - { - throw new RuntimeException("Invalid point compression"); - } - - BigInteger betaValue = beta.toBigInteger(); - if (betaValue.testBit(0) != (yTilde == 1)) - { - // Use the other root - beta = fromBigInteger(q.subtract(betaValue)); - } - - return new ECPoint.Fp(this, x, beta, true); - } - public ECPoint getInfinity() { return infinity; } + } - public boolean equals( - Object anObject) + public static abstract class AbstractF2m extends ECCurve + { + private static FiniteField buildField(int m, int k1, int k2, int k3) { - if (anObject == this) + if (k1 == 0) { - return true; + throw new IllegalArgumentException("k1 must be > 0"); } - if (!(anObject instanceof ECCurve.Fp)) + if (k2 == 0) { - return false; + if (k3 != 0) + { + throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); + } + + return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, m }); } - ECCurve.Fp other = (ECCurve.Fp) anObject; + if (k2 <= k1) + { + throw new IllegalArgumentException("k2 must be > k1"); + } - return this.q.equals(other.q) - && a.equals(other.a) && b.equals(other.b); + if (k3 <= k2) + { + throw new IllegalArgumentException("k3 must be > k2"); + } + + return FiniteFields.getBinaryExtensionField(new int[]{ 0, k1, k2, k3, m }); } - public int hashCode() + protected AbstractF2m(int m, int k1, int k2, int k3) { - return a.hashCode() ^ b.hashCode() ^ q.hashCode(); + super(buildField(m, k1, k2, k3)); } } @@ -464,9 +645,9 @@ public abstract class ECCurve * Elliptic curves over F2m. The Weierstrass equation is given by *y2 + xy = x3 + ax2 + b
. */ - public static class F2m extends ECCurve + public static class F2m extends AbstractF2m { - private static final int F2M_DEFAULT_COORDS = COORD_AFFINE; + private static final int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE; /** * The exponentm
ofF2m
. @@ -498,16 +679,6 @@ public abstract class ECCurve * represents the reduction polynomialf(z)
.
*/ private int k3; // can't be final - JDK 1.1 - - /** - * The order of the base point of the curve. - */ - private BigInteger n; // can't be final - JDK 1.1 - - /** - * The cofactor of the curve. - */ - private BigInteger h; // can't be final - JDK 1.1 /** * The point at infinity on this curve. @@ -563,8 +734,8 @@ public abstract class ECCurve * @param b The coefficientb
in the Weierstrass equation * for non-supersingular elliptic curves over *F2m
. - * @param n The order of the main subgroup of the elliptic curve. - * @param h The cofactor of the elliptic curve, i.e. + * @param order The order of the main subgroup of the elliptic curve. + * @param cofactor The cofactor of the elliptic curve, i.e. *#Ea(F2m) = h * n
. */ public F2m( @@ -572,10 +743,10 @@ public abstract class ECCurve int k, BigInteger a, BigInteger b, - BigInteger n, - BigInteger h) + BigInteger order, + BigInteger cofactor) { - this(m, k, 0, 0, a, b, n, h); + this(m, k, 0, 0, a, b, order, cofactor); } /** @@ -628,8 +799,8 @@ public abstract class ECCurve * @param b The coefficientb
in the Weierstrass equation * for non-supersingular elliptic curves over *F2m
. - * @param n The order of the main subgroup of the elliptic curve. - * @param h The cofactor of the elliptic curve, i.e. + * @param order The order of the main subgroup of the elliptic curve. + * @param cofactor The cofactor of the elliptic curve, i.e. *#Ea(F2m) = h * n
. */ public F2m( @@ -639,40 +810,17 @@ public abstract class ECCurve int k3, BigInteger a, BigInteger b, - BigInteger n, - BigInteger h) + BigInteger order, + BigInteger cofactor) { + super(m, k1, k2, k3); + this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; - this.n = n; - this.h = h; - - if (k1 == 0) - { - throw new IllegalArgumentException("k1 must be > 0"); - } - - if (k2 == 0) - { - if (k3 != 0) - { - throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); - } - } - else - { - if (k2 <= k1) - { - throw new IllegalArgumentException("k2 must be > k1"); - } - - if (k3 <= k2) - { - throw new IllegalArgumentException("k3 must be > k2"); - } - } + this.order = order; + this.cofactor = cofactor; this.infinity = new ECPoint.F2m(this, null, null); this.a = fromBigInteger(a); @@ -680,14 +828,16 @@ public abstract class ECCurve this.coord = F2M_DEFAULT_COORDS; } - protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger n, BigInteger h) + protected F2m(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor) { + super(m, k1, k2, k3); + this.m = m; this.k1 = k1; this.k2 = k2; this.k3 = k3; - this.n = n; - this.h = h; + this.order = order; + this.cofactor = cofactor; this.infinity = new ECPoint.F2m(this, null, null); this.a = a; @@ -697,7 +847,7 @@ public abstract class ECCurve protected ECCurve cloneCurve() { - return new F2m(m, k1, k2, k3, a, b, n, h); + return new F2m(m, k1, k2, k3, a, b, order, cofactor); } public boolean supportsCoordinateSystem(int coord) @@ -742,7 +892,14 @@ public abstract class ECCurve case COORD_LAMBDA_AFFINE: case COORD_LAMBDA_PROJECTIVE: { - if (!X.isZero()) + if (X.isZero()) + { + if (!Y.square().equals(this.getB())) + { + throw new IllegalArgumentException(); + } + } + else { // Y becomes Lambda (X + Y/X) here Y = Y.divide(X).add(X); @@ -763,6 +920,11 @@ public abstract class ECCurve return new ECPoint.F2m(this, x, y, withCompression); } + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new ECPoint.F2m(this, x, y, zs, withCompression); + } + public ECPoint getInfinity() { return infinity; @@ -774,7 +936,7 @@ public abstract class ECCurve */ public boolean isKoblitz() { - return n != null && h != null && a.bitLength() <= 1 && b.bitLength() == 1; + return order != null && cofactor != null && b.isOne() && (a.isZero() || a.isOne()); } /** @@ -817,49 +979,47 @@ public abstract class ECCurve */ protected ECPoint decompressPoint(int yTilde, BigInteger X1) { - ECFieldElement xp = fromBigInteger(X1); - ECFieldElement yp = null; - if (xp.isZero()) + ECFieldElement x = fromBigInteger(X1), y = null; + if (x.isZero()) { - yp = (ECFieldElement.F2m)b; - for (int i = 0; i < m - 1; i++) - { - yp = yp.square(); - } + y = b.sqrt(); } else { - ECFieldElement beta = xp.add(a).add(b.multiply(xp.square().invert())); + ECFieldElement beta = x.square().invert().multiply(b).add(a).add(x); ECFieldElement z = solveQuadraticEquation(beta); - if (z == null) + if (z != null) { - throw new IllegalArgumentException("Invalid point compression"); - } - if (z.testBitZero() != (yTilde == 1)) - { - z = z.addOne(); - } + if (z.testBitZero() != (yTilde == 1)) + { + z = z.addOne(); + } - yp = xp.multiply(z); - - switch (this.getCoordinateSystem()) - { - case COORD_LAMBDA_AFFINE: - case COORD_LAMBDA_PROJECTIVE: - { - yp = yp.divide(xp).add(xp); - break; - } - default: - { - break; - } + switch (this.getCoordinateSystem()) + { + case COORD_LAMBDA_AFFINE: + case COORD_LAMBDA_PROJECTIVE: + { + y = z.add(x); + break; + } + default: + { + y = z.multiply(x); + break; + } + } } } - return new ECPoint.F2m(this, xp, yp, true); + if (y == null) + { + throw new IllegalArgumentException("Invalid point compression"); + } + + return this.createRawPoint(x, y, true); } - + /** * Solves a quadratic equationz2 + z = beta
(X9.62 * D.1.6) The other solution isz + 1
. @@ -903,31 +1063,6 @@ public abstract class ECCurve return z; } - - public boolean equals( - Object anObject) - { - if (anObject == this) - { - return true; - } - - if (!(anObject instanceof ECCurve.F2m)) - { - return false; - } - - ECCurve.F2m other = (ECCurve.F2m)anObject; - - return (this.m == other.m) && (this.k1 == other.k1) - && (this.k2 == other.k2) && (this.k3 == other.k3) - && a.equals(other.a) && b.equals(other.b); - } - - public int hashCode() - { - return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; - } public int getM() { @@ -959,14 +1094,20 @@ public abstract class ECCurve return k3; } + /** + * @deprecated use {@link #getOrder()} instead + */ public BigInteger getN() { - return n; + return order; } + /** + * @deprecated use {@link #getCofactor()} instead + */ public BigInteger getH() { - return h; + return cofactor; } } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java index d72d50782..f96b8e61d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECFieldElement.java @@ -3,6 +3,8 @@ package org.spongycastle.math.ec; import java.math.BigInteger; import java.util.Random; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat; import org.spongycastle.util.Arrays; import org.spongycastle.util.BigIntegers; @@ -27,11 +29,36 @@ public abstract class ECFieldElement return toBigInteger().bitLength(); } + public boolean isOne() + { + return bitLength() == 1; + } + public boolean isZero() { return 0 == toBigInteger().signum(); } + public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return multiply(b).subtract(x.multiply(y)); + } + + public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return multiply(b).add(x.multiply(y)); + } + + public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return square().subtract(x.multiply(y)); + } + + public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) + { + return square().add(x.multiply(y)); + } + public boolean testBitZero() { return toBigInteger().testBit(0); @@ -51,42 +78,10 @@ public abstract class ECFieldElement { BigInteger q, r, x; -// static int[] calculateNaf(BigInteger p) -// { -// int[] naf = WNafUtil.generateCompactNaf(p); -// -// int bit = 0; -// for (int i = 0; i < naf.length; ++i) -// { -// int ni = naf[i]; -// int digit = ni >> 16, zeroes = ni & 0xFFFF; -// -// bit += zeroes; -// naf[i] = digit < 0 ? ~bit : bit; -// ++bit; -// } -// -// int last = naf.length - 1; -// if (last > 0 && last <= 16) -// { -// int top = naf[last], top2 = naf[last - 1]; -// if (top2 < 0) -// { -// top2 = ~top2; -// } -// if (top - top2 >= 64) -// { -// return naf; -// } -// } -// -// return null; -// } - static BigInteger calculateResidue(BigInteger p) { int bitLength = p.bitLength(); - if (bitLength > 128) + if (bitLength >= 96) { BigInteger firstWord = p.shiftRight(bitLength - 64); if (firstWord.longValue() == -1L) @@ -159,13 +154,7 @@ public abstract class ECFieldElement public ECFieldElement subtract(ECFieldElement b) { - BigInteger x2 = b.toBigInteger(); - BigInteger x3 = x.subtract(x2); - if (x3.signum() < 0) - { - x3 = x3.add(q); - } - return new Fp(q, r, x3); + return new Fp(q, r, modSubtract(x, b.toBigInteger())); } public ECFieldElement multiply(ECFieldElement b) @@ -173,27 +162,30 @@ public abstract class ECFieldElement return new Fp(q, r, modMult(x, b.toBigInteger())); } + public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger(); + BigInteger ab = ax.multiply(bx); + BigInteger xy = xx.multiply(yx); + return new Fp(q, r, modReduce(ab.subtract(xy))); + } + + public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + BigInteger ax = this.x, bx = b.toBigInteger(), xx = x.toBigInteger(), yx = y.toBigInteger(); + BigInteger ab = ax.multiply(bx); + BigInteger xy = xx.multiply(yx); + return new Fp(q, r, modReduce(ab.add(xy))); + } + public ECFieldElement divide(ECFieldElement b) { - return new Fp(q, modMult(x, b.toBigInteger().modInverse(q))); + return new Fp(q, r, modMult(x, modInverse(b.toBigInteger()))); } public ECFieldElement negate() { - BigInteger x2; - if (x.signum() == 0) - { - x2 = x; - } - else if (ONE.equals(r)) - { - x2 = q.xor(x); - } - else - { - x2 = q.subtract(x); - } - return new Fp(q, r, x2); + return x.signum() == 0 ? this : new Fp(q, r, q.subtract(x)); } public ECFieldElement square() @@ -201,10 +193,26 @@ public abstract class ECFieldElement return new Fp(q, r, modMult(x, x)); } + public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) + { + BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger(); + BigInteger aa = ax.multiply(ax); + BigInteger xy = xx.multiply(yx); + return new Fp(q, r, modReduce(aa.subtract(xy))); + } + + public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) + { + BigInteger ax = this.x, xx = x.toBigInteger(), yx = y.toBigInteger(); + BigInteger aa = ax.multiply(ax); + BigInteger xy = xx.multiply(yx); + return new Fp(q, r, modReduce(aa.add(xy))); + } + public ECFieldElement invert() { // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime. - return new Fp(q, r, x.modInverse(q)); + return new Fp(q, r, modInverse(x)); } // D.1.4 91 @@ -214,6 +222,11 @@ public abstract class ECFieldElement */ public ECFieldElement sqrt() { + if (this.isZero() || this.isOne()) // earlier JDK compatibility + { + return this; + } + if (!q.testBit(0)) { throw new RuntimeException("not done yet"); @@ -221,29 +234,44 @@ public abstract class ECFieldElement // note: even though this class implements ECConstants don't be tempted to // remove the explicit declaration, some J2ME environments don't cope. - // p mod 4 == 3 - if (q.testBit(1)) - { - // z = g^(u+1) + p, p = 4u + 3 - ECFieldElement z = new Fp(q, r, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q)); - return z.square().equals(this) ? z : null; + if (q.testBit(1)) // q == 4m + 3 + { + BigInteger e = q.shiftRight(2).add(ECConstants.ONE); + return checkSqrt(new Fp(q, r, x.modPow(e, q))); } - // p mod 4 == 1 - BigInteger qMinusOne = q.subtract(ECConstants.ONE); + if (q.testBit(2)) // q == 8m + 5 + { + BigInteger t1 = x.modPow(q.shiftRight(3), q); + BigInteger t2 = modMult(t1, x); + BigInteger t3 = modMult(t2, t1); - BigInteger legendreExponent = qMinusOne.shiftRight(1); + if (t3.equals(ECConstants.ONE)) + { + return checkSqrt(new Fp(q, r, t2)); + } + + // TODO This is constant and could be precomputed + BigInteger t4 = ECConstants.TWO.modPow(q.shiftRight(2), q); + + BigInteger y = modMult(t2, t4); + + return checkSqrt(new Fp(q, r, y)); + } + + // q == 8m + 1 + + BigInteger legendreExponent = q.shiftRight(1); if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) { return null; } - BigInteger u = qMinusOne.shiftRight(2); - BigInteger k = u.shiftLeft(1).add(ECConstants.ONE); + BigInteger X = this.x; + BigInteger fourX = modDouble(modDouble(X)); - BigInteger Q = this.x; - BigInteger fourQ = modDouble(modDouble(Q)); + BigInteger k = legendreExponent.add(ECConstants.ONE), qMinusOne = q.subtract(ECConstants.ONE); BigInteger U, V; Random rand = new Random(); @@ -255,94 +283,39 @@ public abstract class ECFieldElement P = new BigInteger(q.bitLength(), rand); } while (P.compareTo(q) >= 0 - || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); + || !modReduce(P.multiply(P).subtract(fourX)).modPow(legendreExponent, q).equals(qMinusOne)); - BigInteger[] result = lucasSequence(P, Q, k); + BigInteger[] result = lucasSequence(P, X, k); U = result[0]; V = result[1]; - if (modMult(V, V).equals(fourQ)) + if (modMult(V, V).equals(fourX)) { - // Integer division by 2, mod q - if (V.testBit(0)) - { - V = V.add(q); - } - - V = V.shiftRight(1); - - //assert V.multiply(V).mod(q).equals(x); - - return new ECFieldElement.Fp(q, r, V); + return new ECFieldElement.Fp(q, r, modHalfAbs(V)); } } while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); return null; - -// BigInteger qMinusOne = q.subtract(ECConstants.ONE); -// BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); -// if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) -// { -// return null; -// } -// -// Random rand = new Random(); -// BigInteger fourX = x.shiftLeft(2); -// -// BigInteger r; -// do -// { -// r = new BigInteger(q.bitLength(), rand); -// } -// while (r.compareTo(q) >= 0 -// || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); -// -// BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); -// BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); -// -// BigInteger wOne = WOne(r, x, q); -// BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); -// BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); -// -// BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q) -// .multiply(x).mod(q) -// .multiply(wSum).mod(q); -// -// return new Fp(q, root); } -// private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p) -// { -// if (n.equals(ECConstants.ONE)) -// { -// return wOne; -// } -// boolean isEven = !n.testBit(0); -// n = n.shiftRight(1);//divide(ECConstants.TWO); -// if (isEven) -// { -// BigInteger w = W(n, wOne, p); -// return w.multiply(w).subtract(ECConstants.TWO).mod(p); -// } -// BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p); -// BigInteger w2 = W(n, wOne, p); -// return w1.multiply(w2).subtract(wOne).mod(p); -// } -// -// private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p) -// { -// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); -// } + private ECFieldElement checkSqrt(ECFieldElement z) + { + return z.square().equals(this) ? z : null; + } private BigInteger[] lucasSequence( BigInteger P, BigInteger Q, BigInteger k) { + // TODO Research and apply "common-multiplicand multiplication here" + int n = k.bitLength(); int s = k.getLowestSetBit(); + // assert k.testBit(s); + BigInteger Uh = ECConstants.ONE; BigInteger Vl = ECConstants.TWO; BigInteger Vh = P; @@ -405,6 +378,35 @@ public abstract class ECFieldElement return _2x; } + protected BigInteger modHalf(BigInteger x) + { + if (x.testBit(0)) + { + x = q.add(x); + } + return x.shiftRight(1); + } + + protected BigInteger modHalfAbs(BigInteger x) + { + if (x.testBit(0)) + { + x = q.subtract(x); + } + return x.shiftRight(1); + } + + protected BigInteger modInverse(BigInteger x) + { + int bits = getFieldSize(); + int len = (bits + 31) >> 5; + int[] p = Nat.fromBigInteger(bits, q); + int[] n = Nat.fromBigInteger(bits, x); + int[] z = Nat.create(len); + Mod.invert(p, n, z); + return Nat.toBigInteger(len, z); + } + protected BigInteger modMult(BigInteger x1, BigInteger x2) { return modReduce(x1.multiply(x2)); @@ -412,44 +414,20 @@ public abstract class ECFieldElement protected BigInteger modReduce(BigInteger x) { -// if (naf != null) -// { -// int last = naf.length - 1; -// int bits = naf[last]; -// while (x.bitLength() > (bits + 1)) -// { -// BigInteger u = x.shiftRight(bits); -// BigInteger v = x.subtract(u.shiftLeft(bits)); -// -// x = v; -// -// for (int i = 0; i < last; ++i) -// { -// int ni = naf[i]; -// if (ni < 0) -// { -// x = x.add(u.shiftLeft(~ni)); -// } -// else -// { -// x = x.subtract(u.shiftLeft(ni)); -// } -// } -// } -// while (x.compareTo(q) >= 0) -// { -// x = x.subtract(q); -// } -// } -// else if (r != null) { + boolean negative = x.signum() < 0; + if (negative) + { + x = x.abs(); + } int qLen = q.bitLength(); + boolean rIsOne = r.equals(ECConstants.ONE); while (x.bitLength() > (qLen + 1)) { BigInteger u = x.shiftRight(qLen); BigInteger v = x.subtract(u.shiftLeft(qLen)); - if (!r.equals(ONE)) + if (!rIsOne) { u = u.multiply(r); } @@ -459,6 +437,10 @@ public abstract class ECFieldElement { x = x.subtract(q); } + if (negative && x.signum() != 0) + { + x = q.subtract(x); + } } else { @@ -467,6 +449,16 @@ public abstract class ECFieldElement return x; } + protected BigInteger modSubtract(BigInteger x1, BigInteger x2) + { + BigInteger x3 = x1.subtract(x2); + if (x3.signum() < 0) + { + x3 = x3.add(q); + } + return x3; + } + public boolean equals(Object other) { if (other == this) @@ -489,467 +481,6 @@ public abstract class ECFieldElement } } -// /** -// * Class representing the Elements of the finite field -// *F2m
in polynomial basis (PB) -// * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial -// * basis representations are supported. Gaussian normal basis (GNB) -// * representation is not supported. -// */ -// public static class F2m extends ECFieldElement -// { -// BigInteger x; -// -// /** -// * Indicates gaussian normal basis representation (GNB). Number chosen -// * according to X9.62. GNB is not implemented at present. -// */ -// public static final int GNB = 1; -// -// /** -// * Indicates trinomial basis representation (TPB). Number chosen -// * according to X9.62. -// */ -// public static final int TPB = 2; -// -// /** -// * Indicates pentanomial basis representation (PPB). Number chosen -// * according to X9.62. -// */ -// public static final int PPB = 3; -// -// /** -// * TPB or PPB. -// */ -// private int representation; -// -// /** -// * The exponentm
ofF2m
. -// */ -// private int m; -// -// /** -// * TPB: The integerk
wherexm + -// * xk + 1
represents the reduction polynomial -// *f(z)
.
-// * PPB: The integerk1
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k1; -// -// /** -// * TPB: Always set to0
-// * PPB: The integerk2
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k2; -// -// /** -// * TPB: Always set to0
-// * PPB: The integerk3
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k3; -// -// /** -// * Constructor for PPB. -// * @param m The exponentm
of -// *F2m
. -// * @param k1 The integerk1
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
. -// * @param k2 The integerk2
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
. -// * @param k3 The integerk3
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
. -// * @param x The BigInteger representing the value of the field element. -// */ -// public F2m( -// int m, -// int k1, -// int k2, -// int k3, -// BigInteger x) -// { -//// super(x); -// this.x = x; -// -// if ((k2 == 0) && (k3 == 0)) -// { -// this.representation = TPB; -// } -// else -// { -// if (k2 >= k3) -// { -// throw new IllegalArgumentException( -// "k2 must be smaller than k3"); -// } -// if (k2 <= 0) -// { -// throw new IllegalArgumentException( -// "k2 must be larger than 0"); -// } -// this.representation = PPB; -// } -// -// if (x.signum() < 0) -// { -// throw new IllegalArgumentException("x value cannot be negative"); -// } -// -// this.m = m; -// this.k1 = k1; -// this.k2 = k2; -// this.k3 = k3; -// } -// -// /** -// * Constructor for TPB. -// * @param m The exponentm
of -// *F2m
. -// * @param k The integerk
wherexm + -// * xk + 1
represents the reduction -// * polynomialf(z)
. -// * @param x The BigInteger representing the value of the field element. -// */ -// public F2m(int m, int k, BigInteger x) -// { -// // Set k1 to k, and set k2 and k3 to 0 -// this(m, k, 0, 0, x); -// } -// -// public BigInteger toBigInteger() -// { -// return x; -// } -// -// public String getFieldName() -// { -// return "F2m"; -// } -// -// public int getFieldSize() -// { -// return m; -// } -// -// /** -// * Checks, if the ECFieldElementsa
andb
-// * are elements of the same fieldF2m
-// * (having the same representation). -// * @param a field element. -// * @param b field element to be compared. -// * @throws IllegalArgumentException ifa
andb
-// * are not elements of the same field -// *F2m
(having the same -// * representation). -// */ -// public static void checkFieldElements( -// ECFieldElement a, -// ECFieldElement b) -// { -// if ((!(a instanceof F2m)) || (!(b instanceof F2m))) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "both instances of ECFieldElement.F2m"); -// } -// -// if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) -// { -// throw new IllegalArgumentException( -// "x value may not be negative"); -// } -// -// ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; -// ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; -// -// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) -// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "elements of the same field F2m"); -// } -// -// if (aF2m.representation != bF2m.representation) -// { -// // Should never occur -// throw new IllegalArgumentException( -// "One of the field " -// + "elements are not elements has incorrect representation"); -// } -// } -// -// /** -// * Computesz * a(z) mod f(z)
, wheref(z)
is -// * the reduction polynomial ofthis
. -// * @param a The polynomiala(z)
to be multiplied by -// *z mod f(z)
. -// * @returnz * a(z) mod f(z)
-// */ -// private BigInteger multZModF(final BigInteger a) -// { -// // Left-shift of a(z) -// BigInteger az = a.shiftLeft(1); -// if (az.testBit(this.m)) -// { -// // If the coefficient of z^m in a(z) equals 1, reduction -// // modulo f(z) is performed: Add f(z) to to a(z): -// // Step 1: Unset mth coeffient of a(z) -// az = az.clearBit(this.m); -// -// // Step 2: Add r(z) to a(z), where r(z) is defined as -// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of -// // the non-zero coefficients in r(z) -// az = az.flipBit(0); -// az = az.flipBit(this.k1); -// if (this.representation == PPB) -// { -// az = az.flipBit(this.k2); -// az = az.flipBit(this.k3); -// } -// } -// return az; -// } -// -// public ECFieldElement add(final ECFieldElement b) -// { -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// if (b.toBigInteger().signum() == 0) -// { -// return this; -// } -// -// return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); -// } -// -// public ECFieldElement subtract(final ECFieldElement b) -// { -// // Addition and subtraction are the same in F2m -// return add(b); -// } -// -// -// public ECFieldElement multiply(final ECFieldElement b) -// { -// // Left-to-right shift-and-add field multiplication in F2m -// // Input: Binary polynomials a(z) and b(z) of degree at most m-1 -// // Output: c(z) = a(z) * b(z) mod f(z) -// -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// final BigInteger az = this.x; -// BigInteger bz = b.toBigInteger(); -// BigInteger cz; -// -// // Compute c(z) = a(z) * b(z) mod f(z) -// if (az.testBit(0)) -// { -// cz = bz; -// } -// else -// { -// cz = ECConstants.ZERO; -// } -// -// for (int i = 1; i < this.m; i++) -// { -// // b(z) := z * b(z) mod f(z) -// bz = multZModF(bz); -// -// if (az.testBit(i)) -// { -// // If the coefficient of x^i in a(z) equals 1, b(z) is added -// // to c(z) -// cz = cz.xor(bz); -// } -// } -// return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); -// } -// -// -// public ECFieldElement divide(final ECFieldElement b) -// { -// // There may be more efficient implementations -// ECFieldElement bInv = b.invert(); -// return multiply(bInv); -// } -// -// public ECFieldElement negate() -// { -// // -x == x holds for all x in F2m -// return this; -// } -// -// public ECFieldElement square() -// { -// // Naive implementation, can probably be speeded up using modular -// // reduction -// return multiply(this); -// } -// -// public ECFieldElement invert() -// { -// // Inversion in F2m using the extended Euclidean algorithm -// // Input: A nonzero polynomial a(z) of degree at most m-1 -// // Output: a(z)^(-1) mod f(z) -// -// // u(z) := a(z) -// BigInteger uz = this.x; -// if (uz.signum() <= 0) -// { -// throw new ArithmeticException("x is zero or negative, " + -// "inversion is impossible"); -// } -// -// // v(z) := f(z) -// BigInteger vz = ECConstants.ZERO.setBit(m); -// vz = vz.setBit(0); -// vz = vz.setBit(this.k1); -// if (this.representation == PPB) -// { -// vz = vz.setBit(this.k2); -// vz = vz.setBit(this.k3); -// } -// -// // g1(z) := 1, g2(z) := 0 -// BigInteger g1z = ECConstants.ONE; -// BigInteger g2z = ECConstants.ZERO; -// -// // while u != 1 -// while (!(uz.equals(ECConstants.ZERO))) -// { -// // j := deg(u(z)) - deg(v(z)) -// int j = uz.bitLength() - vz.bitLength(); -// -// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j -// if (j < 0) -// { -// final BigInteger uzCopy = uz; -// uz = vz; -// vz = uzCopy; -// -// final BigInteger g1zCopy = g1z; -// g1z = g2z; -// g2z = g1zCopy; -// -// j = -j; -// } -// -// // u(z) := u(z) + z^j * v(z) -// // Note, that no reduction modulo f(z) is required, because -// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) -// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) -// // = deg(u(z)) -// uz = uz.xor(vz.shiftLeft(j)); -// -// // g1(z) := g1(z) + z^j * g2(z) -// g1z = g1z.xor(g2z.shiftLeft(j)); -//// if (g1z.bitLength() > this.m) { -//// throw new ArithmeticException( -//// "deg(g1z) >= m, g1z = " + g1z.toString(16)); -//// } -// } -// return new ECFieldElement.F2m( -// this.m, this.k1, this.k2, this.k3, g2z); -// } -// -// public ECFieldElement sqrt() -// { -// throw new RuntimeException("Not implemented"); -// } -// -// /** -// * @return the representation of the field -// *F2m
, either of -// * TPB (trinomial -// * basis representation) or -// * PPB (pentanomial -// * basis representation). -// */ -// public int getRepresentation() -// { -// return this.representation; -// } -// -// /** -// * @return the degreem
of the reduction polynomial -// *f(z)
. -// */ -// public int getM() -// { -// return this.m; -// } -// -// /** -// * @return TPB: The integerk
wherexm + -// * xk + 1
represents the reduction polynomial -// *f(z)
.
-// * PPB: The integerk1
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// public int getK1() -// { -// return this.k1; -// } -// -// /** -// * @return TPB: Always returns0
-// * PPB: The integerk2
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// public int getK2() -// { -// return this.k2; -// } -// -// /** -// * @return TPB: Always set to0
-// * PPB: The integerk3
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// public int getK3() -// { -// return this.k3; -// } -// -// public boolean equals(Object anObject) -// { -// if (anObject == this) -// { -// return true; -// } -// -// if (!(anObject instanceof ECFieldElement.F2m)) -// { -// return false; -// } -// -// ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; -// -// return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) -// && (this.k3 == b.k3) -// && (this.representation == b.representation) -// && (this.x.equals(b.x))); -// } -// -// public int hashCode() -// { -// return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; -// } -// } - /** * Class representing the Elements of the finite field *F2m
in polynomial basis (PB) @@ -987,32 +518,6 @@ public abstract class ECFieldElement */ private int m; -// /** -// * TPB: The integerk
wherexm + -// * xk + 1
represents the reduction polynomial -// *f(z)
.
-// * PPB: The integerk1
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k1; -// -// /** -// * TPB: Always set to0
-// * PPB: The integerk2
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k2; -// -// /** -// * TPB: Always set to0
-// * PPB: The integerk3
wherexm + -// * xk3 + xk2 + xk1 + 1
-// * represents the reduction polynomialf(z)
.
-// */ -// private int k3; - private int[] ks; /** @@ -1097,6 +602,11 @@ public abstract class ECFieldElement return x.degree(); } + public boolean isOne() + { + return x.isOne(); + } + public boolean isZero() { return x.isZero(); @@ -1192,6 +702,29 @@ public abstract class ECFieldElement return new F2m(m, ks, x.modMultiply(((F2m)b).x, m, ks)); } + public ECFieldElement multiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + return multiplyPlusProduct(b, x, y); + } + + public ECFieldElement multiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y) + { + LongArray ax = this.x, bx = ((F2m)b).x, xx = ((F2m)x).x, yx = ((F2m)y).x; + + LongArray ab = ax.multiply(bx, m, ks); + LongArray xy = xx.multiply(yx, m, ks); + + if (ab == ax || ab == bx) + { + ab = (LongArray)ab.clone(); + } + + ab.addShiftedByWords(xy, 0); + ab.reduce(m, ks); + + return new F2m(m, ks, ab); + } + public ECFieldElement divide(final ECFieldElement b) { // There may be more efficient implementations @@ -1210,6 +743,29 @@ public abstract class ECFieldElement return new F2m(m, ks, x.modSquare(m, ks)); } + public ECFieldElement squareMinusProduct(ECFieldElement x, ECFieldElement y) + { + return squarePlusProduct(x, y); + } + + public ECFieldElement squarePlusProduct(ECFieldElement x, ECFieldElement y) + { + LongArray ax = this.x, xx = ((F2m)x).x, yx = ((F2m)y).x; + + LongArray aa = ax.square(m, ks); + LongArray xy = xx.multiply(yx, m, ks); + + if (aa == ax) + { + aa = (LongArray)aa.clone(); + } + + aa.addShiftedByWords(xy, 0); + aa.reduce(m, ks); + + return new F2m(m, ks, aa); + } + public ECFieldElement invert() { return new ECFieldElement.F2m(this.m, this.ks, this.x.modInverse(m, ks)); @@ -1217,7 +773,14 @@ public abstract class ECFieldElement public ECFieldElement sqrt() { - throw new RuntimeException("Not implemented"); + LongArray x1 = this.x; + if (x1.isOne() || x1.isZero()) + { + return this; + } + + LongArray x2 = x1.modSquareN(m - 1, m, ks); + return new ECFieldElement.F2m(m, ks, x2); } /** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java index 81d7d0957..d5783ada8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPoint.java @@ -1,6 +1,7 @@ package org.spongycastle.math.ec; import java.math.BigInteger; +import java.util.Hashtable; /** * base class for points on elliptic curves. @@ -47,7 +48,8 @@ public abstract class ECPoint protected boolean withCompression; - protected PreCompInfo preCompInfo = null; + // Hashtable is (String -> PreCompInfo) + protected Hashtable preCompTable = null; protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) { @@ -62,11 +64,26 @@ public abstract class ECPoint this.zs = zs; } + protected boolean satisfiesCofactor() + { + BigInteger h = curve.getCofactor(); + return h == null || h.equals(ECConstants.ONE) || !ECAlgorithms.referenceMultiply(this, h).isInfinity(); + } + + protected abstract boolean satisfiesCurveEquation(); + + public final ECPoint getDetachedPoint() + { + return normalize().detach(); + } + public ECCurve getCurve() { return curve; } + protected abstract ECPoint detach(); + protected int getCurveCoordinateSystem() { // Cope with null curve, most commonly used by implicitlyCa @@ -79,7 +96,7 @@ public abstract class ECPoint * Note: normalization can be expensive, this method is deprecated in favour * of caller-controlled normalization. * - * @deprecated Use getAffineXCoord, or normalize() and getXCoord(), instead + * @deprecated Use getAffineXCoord(), or normalize() and getXCoord(), instead */ public ECFieldElement getX() { @@ -93,7 +110,7 @@ public abstract class ECPoint * Note: normalization can be expensive, this method is deprecated in favour * of caller-controlled normalization. * - * @deprecated Use getAffineYCoord, or normalize() and getYCoord(), instead + * @deprecated Use getAffineYCoord(), or normalize() and getYCoord(), instead */ public ECFieldElement getY() { @@ -129,7 +146,7 @@ public abstract class ECPoint * * Caution: depending on the curve's coordinate system, this may not be the same value as in an * affine coordinate system; use normalize() to get a point where the coordinates have their - * affine values, or use getAffineXCoord if you expect the point to already have been + * affine values, or use getAffineXCoord() if you expect the point to already have been * normalized. * * @return the x-coordinate of this point @@ -144,7 +161,7 @@ public abstract class ECPoint * * Caution: depending on the curve's coordinate system, this may not be the same value as in an * affine coordinate system; use normalize() to get a point where the coordinates have their - * affine values, or use getAffineYCoord if you expect the point to already have been + * affine values, or use getAffineYCoord() if you expect the point to already have been * normalized. * * @return the y-coordinate of this point @@ -171,16 +188,21 @@ public abstract class ECPoint return copy; } - protected ECFieldElement getRawXCoord() + protected final ECFieldElement getRawXCoord() { return x; } - protected ECFieldElement getRawYCoord() + protected final ECFieldElement getRawYCoord() { return y; } + protected final ECFieldElement[] getRawZCoords() + { + return zs; + } + protected void checkNormalized() { if (!isNormalized()) @@ -196,7 +218,7 @@ public abstract class ECPoint return coord == ECCurve.COORD_AFFINE || coord == ECCurve.COORD_LAMBDA_AFFINE || isInfinity() - || zs[0].bitLength() == 1; + || zs[0].isOne(); } /** @@ -222,7 +244,7 @@ public abstract class ECPoint default: { ECFieldElement Z1 = getZCoord(0); - if (Z1.bitLength() == 1) + if (Z1.isOne()) { return this; } @@ -270,6 +292,46 @@ public abstract class ECPoint return this.withCompression; } + public boolean isValid() + { + if (isInfinity()) + { + return true; + } + + // TODO Sanity-check the field elements + + ECCurve curve = getCurve(); + if (curve != null) + { + if (!satisfiesCurveEquation()) + { + return false; + } + + if (!satisfiesCofactor()) + { + return false; + } + } + + return true; + } + + public ECPoint scaleX(ECFieldElement scale) + { + return isInfinity() + ? this + : getCurve().createRawPoint(getRawXCoord().multiply(scale), getRawYCoord(), getRawZCoords(), this.withCompression); + } + + public ECPoint scaleY(ECFieldElement scale) + { + return isInfinity() + ? this + : getCurve().createRawPoint(getRawXCoord(), getRawYCoord().multiply(scale), getRawZCoords(), this.withCompression); + } + public boolean equals(ECPoint other) { if (null == other) @@ -454,13 +516,84 @@ public abstract class ECPoint return this.getCurve().getMultiplier().multiply(this, k); } + public static abstract class AbstractFp extends ECPoint + { + protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y) + { + super(curve, x, y); + } + + protected AbstractFp(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs) + { + super(curve, x, y, zs); + } + + protected boolean getCompressionYTilde() + { + return this.getAffineYCoord().testBitZero(); + } + + protected boolean satisfiesCurveEquation() + { + ECFieldElement X = this.x, Y = this.y, A = curve.getA(), B = curve.getB(); + ECFieldElement lhs = Y.square(); + + switch (this.getCurveCoordinateSystem()) + { + case ECCurve.COORD_AFFINE: + break; + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z = this.zs[0]; + if (!Z.isOne()) + { + ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2); + lhs = lhs.multiply(Z); + A = A.multiply(Z2); + B = B.multiply(Z3); + } + break; + } + case ECCurve.COORD_JACOBIAN: + case ECCurve.COORD_JACOBIAN_CHUDNOVSKY: + case ECCurve.COORD_JACOBIAN_MODIFIED: + { + ECFieldElement Z = this.zs[0]; + if (!Z.isOne()) + { + ECFieldElement Z2 = Z.square(), Z4 = Z2.square(), Z6 = Z2.multiply(Z4); + A = A.multiply(Z4); + B = B.multiply(Z6); + } + break; + } + default: + throw new IllegalStateException("unsupported coordinate system"); + } + + ECFieldElement rhs = X.square().add(A).multiply(X).add(B); + return lhs.equals(rhs); + } + + public ECPoint subtract(ECPoint b) + { + if (b.isInfinity()) + { + return this; + } + + // Add -b + return this.add(b.negate()); + } + } + /** * Elliptic curve points over Fp */ - public static class Fp extends ECPoint + public static class Fp extends AbstractFp { /** - * Create a point which encodes with point compression. + * Create a point which encodes without point compression. * * @param curve the curve to use * @param x affine x co-ordinate @@ -474,7 +607,7 @@ public abstract class ECPoint } /** - * Create a point that encodes with or without point compresion. + * Create a point that encodes with or without point compression. * * @param curve the curve to use * @param x affine x co-ordinate @@ -487,7 +620,7 @@ public abstract class ECPoint { super(curve, x, y); - if ((x != null && y == null) || (x == null && y != null)) + if ((x == null) != (y == null)) { throw new IllegalArgumentException("Exactly one of the field elements is null"); } @@ -502,9 +635,9 @@ public abstract class ECPoint this.withCompression = withCompression; } - protected boolean getCompressionYTilde() + protected ECPoint detach() { - return this.getAffineYCoord().testBitZero(); + return new ECPoint.Fp(null, this.getAffineXCoord(), this.getAffineYCoord()); } public ECFieldElement getZCoord(int index) @@ -569,8 +702,8 @@ public abstract class ECPoint ECFieldElement Z1 = this.zs[0]; ECFieldElement Z2 = b.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; - boolean Z2IsOne = Z2.bitLength() == 1; + boolean Z1IsOne = Z1.isOne(); + boolean Z2IsOne = Z2.isOne(); ECFieldElement u1 = Z1IsOne ? Y2 : Y2.multiply(Z1); ECFieldElement u2 = Z2IsOne ? Y1 : Y1.multiply(Z2); @@ -600,7 +733,7 @@ public abstract class ECPoint ECFieldElement A = u.square().multiply(w).subtract(vCubed).subtract(two(vSquaredV2)); ECFieldElement X3 = v.multiply(A); - ECFieldElement Y3 = vSquaredV2.subtract(A).multiply(u).subtract(vCubed.multiply(u2)); + ECFieldElement Y3 = vSquaredV2.subtract(A).multiplyMinusProduct(u, u2, vCubed); ECFieldElement Z3 = vCubed.multiply(w); return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); @@ -612,7 +745,7 @@ public abstract class ECPoint ECFieldElement Z1 = this.zs[0]; ECFieldElement Z2 = b.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; + boolean Z1IsOne = Z1.isOne(); ECFieldElement X3, Y3, Z3, Z3Squared = null; @@ -662,7 +795,7 @@ public abstract class ECPoint S2 = Z1Cubed.multiply(Y2); } - boolean Z2IsOne = Z2.bitLength() == 1; + boolean Z2IsOne = Z2.isOne(); ECFieldElement Z2Squared, U1, S1; if (Z2IsOne) { @@ -697,8 +830,8 @@ public abstract class ECPoint ECFieldElement V = HSquared.multiply(U1); X3 = R.square().add(G).subtract(two(V)); - Y3 = V.subtract(X3).multiply(R).subtract(S1.multiply(G)); - + Y3 = V.subtract(X3).multiplyMinusProduct(R, G, S1); + Z3 = H; if (!Z1IsOne) { @@ -735,6 +868,7 @@ public abstract class ECPoint return new ECPoint.Fp(curve, X3, Y3, zs, this.withCompression); } + default: { throw new IllegalStateException("unsupported coordinate system"); @@ -778,14 +912,13 @@ public abstract class ECPoint { ECFieldElement Z1 = this.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; - ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square(); + boolean Z1IsOne = Z1.isOne(); // TODO Optimize for small negative a4 and -3 ECFieldElement w = curve.getA(); - if (!Z1IsOne) + if (!w.isZero() && !Z1IsOne) { - w = w.multiply(Z1Squared); + w = w.multiply(Z1.square()); } w = w.add(three(X1.square())); @@ -795,9 +928,11 @@ public abstract class ECPoint ECFieldElement _4B = four(B); ECFieldElement h = w.square().subtract(two(_4B)); - ECFieldElement X3 = two(h.multiply(s)); - ECFieldElement Y3 = w.multiply(_4B.subtract(h)).subtract(two(two(t).square())); - ECFieldElement _4sSquared = Z1IsOne ? four(t) : two(s).square(); + ECFieldElement _2s = two(s); + ECFieldElement X3 = h.multiply(_2s); + ECFieldElement _2t = two(t); + ECFieldElement Y3 = _4B.subtract(h).multiply(w).subtract(two(_2t.square())); + ECFieldElement _4sSquared = Z1IsOne ? two(_2t) : _2s.square(); ECFieldElement Z3 = two(_4sSquared).multiply(s); return new ECPoint.Fp(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); @@ -807,8 +942,7 @@ public abstract class ECPoint { ECFieldElement Z1 = this.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; - ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square(); + boolean Z1IsOne = Z1.isOne(); ECFieldElement Y1Squared = Y1.square(); ECFieldElement T = Y1Squared.square(); @@ -819,6 +953,7 @@ public abstract class ECPoint ECFieldElement M, S; if (a4Neg.toBigInteger().equals(BigInteger.valueOf(3))) { + ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square(); M = three(X1.add(Z1Squared).multiply(X1.subtract(Z1Squared))); S = four(Y1Squared.multiply(X1)); } @@ -830,8 +965,9 @@ public abstract class ECPoint { M = M.add(a4); } - else + else if (!a4.isZero()) { + ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square(); ECFieldElement Z1Pow4 = Z1Squared.square(); if (a4Neg.bitLength() < a4.bitLength()) { @@ -842,7 +978,8 @@ public abstract class ECPoint M = M.add(Z1Pow4.multiply(a4)); } } - S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T)); +// S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T)); + S = four(X1.multiply(Y1Squared)); } ECFieldElement X3 = M.square().subtract(two(S)); @@ -951,7 +1088,13 @@ public abstract class ECPoint public ECPoint threeTimes() { - if (this.isInfinity() || this.y.isZero()) + if (this.isInfinity()) + { + return this; + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) { return this; } @@ -963,7 +1106,7 @@ public abstract class ECPoint { case ECCurve.COORD_AFFINE: { - ECFieldElement X1 = this.x, Y1 = this.y; + ECFieldElement X1 = this.x; ECFieldElement _2Y1 = two(Y1); ECFieldElement X = _2Y1.square(); @@ -997,6 +1140,98 @@ public abstract class ECPoint } } + public ECPoint timesPow2(int e) + { + if (e < 0) + { + throw new IllegalArgumentException("'e' cannot be negative"); + } + if (e == 0 || this.isInfinity()) + { + return this; + } + if (e == 1) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + int coord = curve.getCoordinateSystem(); + + ECFieldElement W1 = curve.getA(); + ECFieldElement X1 = this.x; + ECFieldElement Z1 = this.zs.length < 1 ? curve.fromBigInteger(ECConstants.ONE) : this.zs[0]; + + if (!Z1.isOne()) + { + switch (coord) + { + case ECCurve.COORD_HOMOGENEOUS: + ECFieldElement Z1Sq = Z1.square(); + X1 = X1.multiply(Z1); + Y1 = Y1.multiply(Z1Sq); + W1 = calculateJacobianModifiedW(Z1, Z1Sq); + break; + case ECCurve.COORD_JACOBIAN: + W1 = calculateJacobianModifiedW(Z1, null); + break; + case ECCurve.COORD_JACOBIAN_MODIFIED: + W1 = getJacobianModifiedW(); + break; + } + } + + for (int i = 0; i < e; ++i) + { + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + ECFieldElement X1Squared = X1.square(); + ECFieldElement M = three(X1Squared); + ECFieldElement _2Y1 = two(Y1); + ECFieldElement _2Y1Squared = _2Y1.multiply(Y1); + ECFieldElement S = two(X1.multiply(_2Y1Squared)); + ECFieldElement _4T = _2Y1Squared.square(); + ECFieldElement _8T = two(_4T); + + if (!W1.isZero()) + { + M = M.add(W1); + W1 = two(_8T.multiply(W1)); + } + + X1 = M.square().subtract(two(S)); + Y1 = M.multiply(S.subtract(X1)).subtract(_8T); + Z1 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1); + } + + switch (coord) + { + case ECCurve.COORD_AFFINE: + ECFieldElement zInv = Z1.invert(), zInv2 = zInv.square(), zInv3 = zInv2.multiply(zInv); + return new Fp(curve, X1.multiply(zInv2), Y1.multiply(zInv3), this.withCompression); + case ECCurve.COORD_HOMOGENEOUS: + X1 = X1.multiply(Z1); + Z1 = Z1.multiply(Z1.square()); + return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression); + case ECCurve.COORD_JACOBIAN: + return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1 }, this.withCompression); + case ECCurve.COORD_JACOBIAN_MODIFIED: + return new Fp(curve, X1, Y1, new ECFieldElement[]{ Z1, W1 }, this.withCompression); + default: + throw new IllegalStateException("unsupported coordinate system"); + } + } + protected ECFieldElement two(ECFieldElement x) { return x.add(x); @@ -1027,18 +1262,6 @@ public abstract class ECPoint return a.add(b).square().subtract(aSquared).subtract(bSquared); } - // 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() { if (this.isInfinity()) @@ -1059,13 +1282,18 @@ public abstract class ECPoint protected ECFieldElement calculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared) { + ECFieldElement a4 = this.getCurve().getA(); + if (a4.isZero() || Z.isOne()) + { + return a4; + } + if (ZSquared == null) { ZSquared = Z.square(); } ECFieldElement W = ZSquared.square(); - ECFieldElement a4 = this.getCurve().getA(); ECFieldElement a4Neg = a4.negate(); if (a4Neg.bitLength() < a4.bitLength()) { @@ -1095,23 +1323,105 @@ public abstract class ECPoint ECFieldElement X1Squared = X1.square(); ECFieldElement M = three(X1Squared).add(W1); - ECFieldElement Y1Squared = Y1.square(); - ECFieldElement T = Y1Squared.square(); - ECFieldElement S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T)); + ECFieldElement _2Y1 = two(Y1); + ECFieldElement _2Y1Squared = _2Y1.multiply(Y1); + ECFieldElement S = two(X1.multiply(_2Y1Squared)); ECFieldElement X3 = M.square().subtract(two(S)); - ECFieldElement _8T = eight(T); + ECFieldElement _4T = _2Y1Squared.square(); + ECFieldElement _8T = two(_4T); ECFieldElement Y3 = M.multiply(S.subtract(X3)).subtract(_8T); ECFieldElement W3 = calculateW ? two(_8T.multiply(W1)) : null; - ECFieldElement Z3 = two(Z1.bitLength() == 1 ? Y1 : Y1.multiply(Z1)); + ECFieldElement Z3 = Z1.isOne() ? _2Y1 : _2Y1.multiply(Z1); return new ECPoint.Fp(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression); } } + public static abstract class AbstractF2m extends ECPoint + { + protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y) + { + super(curve, x, y); + } + + protected AbstractF2m(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs) + { + super(curve, x, y, zs); + } + + protected boolean satisfiesCurveEquation() + { + ECCurve curve = this.getCurve(); + ECFieldElement X = this.x, A = curve.getA(), B = curve.getB(); + + int coord = curve.getCoordinateSystem(); + if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE) + { + ECFieldElement Z = this.zs[0]; + boolean ZIsOne = Z.isOne(); + + if (X.isZero()) + { + // NOTE: For x == 0, we expect the affine-y instead of the lambda-y + ECFieldElement Y = this.y; + ECFieldElement lhs = Y.square(), rhs = B; + if (!ZIsOne) + { + rhs = rhs.multiply(Z.square()); + } + return lhs.equals(rhs); + } + + ECFieldElement L = this.y, X2 = X.square(); + ECFieldElement lhs, rhs; + if (ZIsOne) + { + lhs = L.square().add(L).add(A); + rhs = X2.square().add(B); + } + else + { + ECFieldElement Z2 = Z.square(), Z4 = Z2.square(); + lhs = L.add(Z).multiplyPlusProduct(L, A, Z2); + // TODO If sqrt(b) is precomputed this can be simplified to a single square + rhs = X2.squarePlusProduct(B, Z4); + } + lhs = lhs.multiply(X2); + return lhs.equals(rhs); + } + + ECFieldElement Y = this.y; + ECFieldElement lhs = Y.add(X).multiply(Y); + + switch (coord) + { + case ECCurve.COORD_AFFINE: + break; + case ECCurve.COORD_HOMOGENEOUS: + { + ECFieldElement Z = this.zs[0]; + if (!Z.isOne()) + { + ECFieldElement Z2 = Z.square(), Z3 = Z.multiply(Z2); + lhs = lhs.multiply(Z); + A = A.multiply(Z); + B = B.multiply(Z3); + } + break; + } + default: + throw new IllegalStateException("unsupported coordinate system"); + } + + ECFieldElement rhs = X.add(A).multiply(X.square()).add(B); + return lhs.equals(rhs); + } + } + /** * Elliptic curve points over F2m */ - public static class F2m extends ECPoint + public static class F2m extends AbstractF2m { /** * @param curve base curve @@ -1137,7 +1447,7 @@ public abstract class ECPoint { super(curve, x, y); - if ((x != null && y == null) || (x == null && y != null)) + if ((x == null) != (y == null)) { throw new IllegalArgumentException("Exactly one of the field elements is null"); } @@ -1168,6 +1478,11 @@ public abstract class ECPoint // checkCurveEquation(); } + protected ECPoint detach() + { + return new ECPoint.F2m(null, this.getAffineXCoord(), this.getAffineYCoord()); // earlier JDK + } + public ECFieldElement getYCoord() { int coord = this.getCurveCoordinateSystem(); @@ -1177,19 +1492,19 @@ public abstract class ECPoint case ECCurve.COORD_LAMBDA_AFFINE: case ECCurve.COORD_LAMBDA_PROJECTIVE: { - // TODO The X == 0 stuff needs further thought - if (this.isInfinity() || x.isZero()) + ECFieldElement X = x, L = y; + + if (this.isInfinity() || X.isZero()) { - return y; + return L; } // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly - ECFieldElement X = x, L = y; - ECFieldElement Y = L.subtract(X).multiply(X); + ECFieldElement Y = L.add(X).multiply(X); if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord) { ECFieldElement Z = zs[0]; - if (Z.bitLength() != 1) + if (!Z.isOne()) { Y = Y.divide(Z); } @@ -1203,6 +1518,74 @@ public abstract class ECPoint } } + public ECPoint scaleX(ECFieldElement scale) + { + if (this.isInfinity()) + { + return this; + } + + int coord = this.getCurveCoordinateSystem(); + + switch (coord) + { + case ECCurve.COORD_LAMBDA_AFFINE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK + + ECFieldElement X2 = X.multiply(scale); + ECFieldElement L2 = L.add(X).divide(scale).add(X2); + + return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK + } + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + // Y is actually Lambda (X + Y/X) here + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(), Z = this.getRawZCoords()[0]; // earlier JDK + + // We scale the Z coordinate also, to avoid an inversion + ECFieldElement X2 = X.multiply(scale.square()); + ECFieldElement L2 = L.add(X).add(X2); + ECFieldElement Z2 = Z.multiply(scale); + + return this.getCurve().createRawPoint(X2, L2, new ECFieldElement[]{ Z2 }, this.withCompression); // earlier JDK + } + default: + { + return super.scaleX(scale); + } + } + } + + public ECPoint scaleY(ECFieldElement scale) + { + if (this.isInfinity()) + { + return this; + } + + int coord = this.getCurveCoordinateSystem(); + + switch (coord) + { + case ECCurve.COORD_LAMBDA_AFFINE: + case ECCurve.COORD_LAMBDA_PROJECTIVE: + { + ECFieldElement X = this.getRawXCoord(), L = this.getRawYCoord(); // earlier JDK + + // Y is actually Lambda (X + Y/X) here + ECFieldElement L2 = L.add(X).multiply(scale).add(X); + + return this.getCurve().createRawPoint(X, L2, this.getRawZCoords(), this.withCompression); // earlier JDK + } + default: + { + return super.scaleY(scale); + } + } + } + protected boolean getCompressionYTilde() { ECFieldElement X = this.getRawXCoord(); @@ -1219,7 +1602,7 @@ public abstract class ECPoint case ECCurve.COORD_LAMBDA_PROJECTIVE: { // Y is actually Lambda (X + Y/X) here - return Y.subtract(X).testBitZero(); + return Y.testBitZero() != X.testBitZero(); } default: { @@ -1289,9 +1672,10 @@ public abstract class ECPoint ECFieldElement Y1 = this.y; ECFieldElement Y2 = b.y; - if (X1.equals(X2)) + ECFieldElement dx = X1.add(X2), dy = Y1.add(Y2); + if (dx.isZero()) { - if (Y1.equals(Y2)) + if (dy.isZero()) { return (ECPoint.F2m)twice(); } @@ -1299,10 +1683,9 @@ public abstract class ECPoint return (ECPoint.F2m)curve.getInfinity(); } - ECFieldElement sumX = X1.add(X2); - ECFieldElement L = Y1.add(Y2).divide(sumX); + ECFieldElement L = dy.divide(dx); - ECFieldElement X3 = L.square().add(L).add(sumX).add(curve.getA()); + ECFieldElement X3 = L.square().add(L).add(dx).add(curve.getA()); ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1); return new ECPoint.F2m(curve, X3, Y3, this.withCompression); @@ -1312,18 +1695,18 @@ public abstract class ECPoint ECFieldElement Y1 = this.y, Z1 = this.zs[0]; ECFieldElement Y2 = b.y, Z2 = b.zs[0]; - boolean Z2IsOne = Z2.bitLength() == 1; + boolean Z2IsOne = Z2.isOne(); - ECFieldElement U1 = Z1.multiply(Y2); + ECFieldElement U1 = Z1.multiply(Y2); ECFieldElement U2 = Z2IsOne ? Y1 : Y1.multiply(Z2); - ECFieldElement U = U1.subtract(U2); + ECFieldElement U = U1.add(U2); ECFieldElement V1 = Z1.multiply(X2); ECFieldElement V2 = Z2IsOne ? X1 : X1.multiply(Z2); - ECFieldElement V = V1.subtract(V2); + ECFieldElement V = V1.add(V2); - if (V1.equals(V2)) + if (V.isZero()) { - if (U1.equals(U2)) + if (U.isZero()) { return (ECPoint.F2m)twice(); } @@ -1331,14 +1714,16 @@ public abstract class ECPoint return (ECPoint.F2m)curve.getInfinity(); } - ECFieldElement VSq = V.square(); + ECFieldElement VSq = V.square(); + ECFieldElement VCu = VSq.multiply(V); ECFieldElement W = Z2IsOne ? Z1 : Z1.multiply(Z2); - ECFieldElement A = U.square().add(U.multiply(V).add(VSq.multiply(curve.getA()))).multiply(W).add(V.multiply(VSq)); + ECFieldElement uv = U.add(V); + ECFieldElement A = uv.multiplyPlusProduct(U, VSq, curve.getA()).multiply(W).add(VCu); ECFieldElement X3 = V.multiply(A); ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.multiply(Z2); - ECFieldElement Y3 = VSqZ2.multiply(U.multiply(X1).add(Y1.multiply(V))).add(A.multiply(U.add(V))); - ECFieldElement Z3 = VSq.multiply(V).multiply(W); + ECFieldElement Y3 = U.multiplyPlusProduct(X1, V, Y1).multiplyPlusProduct(VSqZ2, uv, A); + ECFieldElement Z3 = VCu.multiply(W); return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); } @@ -1346,13 +1731,18 @@ public abstract class ECPoint { if (X1.isZero()) { + if (X2.isZero()) + { + return (ECPoint.F2m)curve.getInfinity(); + } + return b.addSimple(this); } ECFieldElement L1 = this.y, Z1 = this.zs[0]; ECFieldElement L2 = b.y, Z2 = b.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; + boolean Z1IsOne = Z1.isOne(); ECFieldElement U2 = X2, S2 = L2; if (!Z1IsOne) { @@ -1360,7 +1750,7 @@ public abstract class ECPoint S2 = S2.multiply(Z1); } - boolean Z2IsOne = Z2.bitLength() == 1; + boolean Z2IsOne = Z2.isOne(); ECFieldElement U1 = X1, S1 = L1; if (!Z2IsOne) { @@ -1385,13 +1775,21 @@ public abstract class ECPoint if (X2.isZero()) { // TODO This can probably be optimized quite a bit + ECPoint p = this.normalize(); + X1 = p.getXCoord(); + ECFieldElement Y1 = p.getYCoord(); - ECFieldElement Y1 = getYCoord(), Y2 = L2; + ECFieldElement Y2 = L2; ECFieldElement L = Y1.add(Y2).divide(X1); X3 = L.square().add(L).add(X1).add(curve.getA()); + if (X3.isZero()) + { + return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression); + } + ECFieldElement Y3 = L.multiply(X1.add(X3)).add(X3).add(Y1); - L3 = X3.isZero() ? Y3 : Y3.divide(X3).add(X3); + L3 = Y3.divide(X3).add(X3); Z3 = curve.fromBigInteger(ECConstants.ONE); } else @@ -1400,14 +1798,20 @@ public abstract class ECPoint ECFieldElement AU1 = A.multiply(U1); ECFieldElement AU2 = A.multiply(U2); + + X3 = AU1.multiply(AU2); + if (X3.isZero()) + { + return new ECPoint.F2m(curve, X3, curve.getB().sqrt(), this.withCompression); + } + ECFieldElement ABZ2 = A.multiply(B); if (!Z2IsOne) { ABZ2 = ABZ2.multiply(Z2); } - X3 = AU1.multiply(AU2); - L3 = AU2.add(B).square().add(ABZ2.multiply(L1.add(Z1))); + L3 = AU2.add(B).squarePlusProduct(ABZ2, L1.add(Z1)); Z3 = ABZ2; if (!Z1IsOne) @@ -1514,7 +1918,7 @@ public abstract class ECPoint ECFieldElement L1 = Y1.divide(X1).add(X1); ECFieldElement X3 = L1.square().add(L1).add(curve.getA()); - ECFieldElement Y3 = X1.square().add(X3.multiply(L1.addOne())); + ECFieldElement Y3 = X1.squarePlusProduct(X3, L1.addOne()); return new ECPoint.F2m(curve, X3, Y3, this.withCompression); } @@ -1522,7 +1926,7 @@ public abstract class ECPoint { ECFieldElement Y1 = this.y, Z1 = this.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; + boolean Z1IsOne = Z1.isOne(); ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1); ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.multiply(Z1); @@ -1530,10 +1934,11 @@ public abstract class ECPoint ECFieldElement S = X1Sq.add(Y1Z1); ECFieldElement V = X1Z1; ECFieldElement vSquared = V.square(); - ECFieldElement h = S.square().add(S.multiply(V)).add(curve.getA().multiply(vSquared)); + ECFieldElement sv = S.add(V); + ECFieldElement h = sv.multiplyPlusProduct(S, vSquared, curve.getA()); ECFieldElement X3 = V.multiply(h); - ECFieldElement Y3 = h.multiply(S.add(V)).add(X1Sq.square().multiply(V)); + ECFieldElement Y3 = X1Sq.square().multiplyPlusProduct(V, h, sv); ECFieldElement Z3 = V.multiply(vSquared); return new ECPoint.F2m(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); @@ -1542,12 +1947,16 @@ public abstract class ECPoint { ECFieldElement L1 = this.y, Z1 = this.zs[0]; - boolean Z1IsOne = Z1.bitLength() == 1; + boolean Z1IsOne = Z1.isOne(); ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.multiply(Z1); ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.square(); ECFieldElement a = curve.getA(); ECFieldElement aZ1Sq = Z1IsOne ? a : a.multiply(Z1Sq); ECFieldElement T = L1.square().add(L1Z1).add(aZ1Sq); + if (T.isZero()) + { + return new ECPoint.F2m(curve, T, curve.getB().sqrt(), withCompression); + } ECFieldElement X3 = T.square(); ECFieldElement Z3 = Z1IsOne ? T : T.multiply(Z1Sq); @@ -1557,14 +1966,30 @@ public abstract class ECPoint if (b.bitLength() < (curve.getFieldSize() >> 1)) { ECFieldElement t1 = L1.add(X1).square(); - ECFieldElement t2 = aZ1Sq.square(); - ECFieldElement t3 = curve.getB().multiply(Z1Sq.square()); - L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2.add(t3)).add(X3).add(a.addOne().multiply(Z3)); + ECFieldElement t2; + if (b.isOne()) + { + t2 = aZ1Sq.add(Z1Sq).square(); + } + else + { + // TODO Can be calculated with one square if we pre-compute sqrt(b) + t2 = aZ1Sq.squarePlusProduct(b, Z1Sq.square()); + } + L3 = t1.add(T).add(Z1Sq).multiply(t1).add(t2).add(X3); + if (a.isZero()) + { + L3 = L3.add(Z3); + } + else if (!a.isOne()) + { + L3 = L3.add(a.addOne().multiply(Z3)); + } } else { ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.multiply(Z1); - L3 = X1Z1.square().add(X3).add(T.multiply(L1Z1)).add(Z3); + L3 = X1Z1.squarePlusProduct(T, L1Z1).add(X3).add(Z3); } return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression); @@ -1604,7 +2029,7 @@ public abstract class ECPoint { // NOTE: twicePlus() only optimized for lambda-affine argument ECFieldElement X2 = b.x, Z2 = b.zs[0]; - if (X2.isZero() || Z2.bitLength() != 1) + if (X2.isZero() || !Z2.isOne()) { return twice().add(b); } @@ -1619,13 +2044,28 @@ public abstract class ECPoint ECFieldElement T = curve.getA().multiply(Z1Sq).add(L1Sq).add(L1Z1); ECFieldElement L2plus1 = L2.addOne(); - ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiply(T).add(X1Sq.multiply(Z1Sq)); + ECFieldElement A = curve.getA().add(L2plus1).multiply(Z1Sq).add(L1Sq).multiplyPlusProduct(T, X1Sq, Z1Sq); ECFieldElement X2Z1Sq = X2.multiply(Z1Sq); ECFieldElement B = X2Z1Sq.add(T).square(); + if (B.isZero()) + { + if (A.isZero()) + { + return b.twice(); + } + + return curve.getInfinity(); + } + + if (A.isZero()) + { + return new ECPoint.F2m(curve, A, curve.getB().sqrt(), withCompression); + } + ECFieldElement X3 = A.square().multiply(X2Z1Sq); ECFieldElement Z3 = A.multiply(B).multiply(Z1Sq); - ECFieldElement L3 = A.add(B).square().multiply(T).add(L2plus1.multiply(Z3)); + ECFieldElement L3 = A.add(B).square().multiplyPlusProduct(T, L2plus1, Z3); return new ECPoint.F2m(curve, X3, L3, new ECFieldElement[]{ Z3 }, this.withCompression); } @@ -1636,57 +2076,6 @@ public abstract class ECPoint } } - protected void checkCurveEquation() - { - if (this.isInfinity()) - { - return; - } - - ECFieldElement Z; - switch (this.getCurveCoordinateSystem()) - { - case ECCurve.COORD_LAMBDA_AFFINE: - Z = curve.fromBigInteger(ECConstants.ONE); - break; - case ECCurve.COORD_LAMBDA_PROJECTIVE: - Z = this.zs[0]; - break; - default: - return; - } - - if (Z.isZero()) - { - throw new IllegalStateException(); - } - - ECFieldElement X = this.x; - if (X.isZero()) - { - // NOTE: For x == 0, we expect the affine-y instead of the lambda-y - ECFieldElement Y = this.y; - if (!Y.square().equals(curve.getB().multiply(Z))) - { - throw new IllegalStateException(); - } - - return; - } - - ECFieldElement L = this.y; - ECFieldElement XSq = X.square(); - ECFieldElement ZSq = Z.square(); - - ECFieldElement lhs = L.square().add(L.multiply(Z)).add(this.getCurve().getA().multiply(ZSq)).multiply(XSq); - ECFieldElement rhs = ZSq.square().multiply(this.getCurve().getB()).add(XSq.square()); - - if (!lhs.equals(rhs)) - { - throw new IllegalStateException("F2m Lambda-Projective invariant broken"); - } - } - public ECPoint negate() { if (this.isInfinity()) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java new file mode 100644 index 000000000..69503585a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ECPointMap.java @@ -0,0 +1,6 @@ +package org.spongycastle.math.ec; + +public interface ECPointMap +{ + ECPoint map(ECPoint p); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java new file mode 100644 index 000000000..42ba2cc86 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointCombMultiplier.java @@ -0,0 +1,57 @@ +package org.spongycastle.math.ec; + +import java.math.BigInteger; + +public class FixedPointCombMultiplier extends AbstractECMultiplier +{ + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) + { + ECCurve c = p.getCurve(); + int size = FixedPointUtil.getCombSize(c); + + if (k.bitLength() > size) + { + /* + * TODO The comb works best when the scalars are less than the (possibly unknown) order. + * Still, if we want to handle larger scalars, we could allow customization of the comb + * size, or alternatively we could deal with the 'extra' bits either by running the comb + * multiple times as necessary, or by using an alternative multiplier as prelude. + */ + throw new IllegalStateException("fixed-point comb doesn't support scalars larger than the curve order"); + } + + int minWidth = getWidthForCombSize(size); + + FixedPointPreCompInfo info = FixedPointUtil.precompute(p, minWidth); + ECPoint[] lookupTable = info.getPreComp(); + int width = info.getWidth(); + + int d = (size + width - 1) / width; + + ECPoint R = c.getInfinity(); + + int top = d * width - 1; + for (int i = 0; i < d; ++i) + { + int index = 0; + + for (int j = top - i; j >= 0; j -= d) + { + index <<= 1; + if (k.testBit(j)) + { + index |= 1; + } + } + + R = R.twicePlus(lookupTable[index]); + } + + return R; + } + + protected int getWidthForCombSize(int combSize) + { + return combSize > 257 ? 6 : 5; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java new file mode 100644 index 000000000..0a14f499b --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointPreCompInfo.java @@ -0,0 +1,40 @@ +package org.spongycastle.math.ec; + +/** + * Class holding precomputation data for fixed-point multiplications. + */ +public class FixedPointPreCompInfo implements PreCompInfo +{ + /** + * Array holding the precomputedECPoint
s used for a fixed + * point multiplication. + */ + protected ECPoint[] preComp = null; + + /** + * The width used for the precomputation. If a larger width precomputation + * is already available this may be larger than was requested, so calling + * code should refer to the actual width. + */ + protected int width = -1; + + public ECPoint[] getPreComp() + { + return preComp; + } + + public void setPreComp(ECPoint[] preComp) + { + this.preComp = preComp; + } + + public int getWidth() + { + return width; + } + + public void setWidth(int width) + { + this.width = width; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java new file mode 100644 index 000000000..aa96ebcb1 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/FixedPointUtil.java @@ -0,0 +1,71 @@ +package org.spongycastle.math.ec; + +import java.math.BigInteger; + +public class FixedPointUtil +{ + public static final String PRECOMP_NAME = "bc_fixed_point"; + + public static int getCombSize(ECCurve c) + { + BigInteger order = c.getOrder(); + return order == null ? c.getFieldSize() + 1 : order.bitLength(); + } + + public static FixedPointPreCompInfo getFixedPointPreCompInfo(PreCompInfo preCompInfo) + { + if ((preCompInfo != null) && (preCompInfo instanceof FixedPointPreCompInfo)) + { + return (FixedPointPreCompInfo)preCompInfo; + } + + return new FixedPointPreCompInfo(); + } + + public static FixedPointPreCompInfo precompute(ECPoint p, int minWidth) + { + ECCurve c = p.getCurve(); + + int n = 1 << minWidth; + FixedPointPreCompInfo info = getFixedPointPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME)); + ECPoint[] lookupTable = info.getPreComp(); + + if (lookupTable == null || lookupTable.length < n) + { + int bits = getCombSize(c); + int d = (bits + minWidth - 1) / minWidth; + + ECPoint[] pow2Table = new ECPoint[minWidth]; + pow2Table[0] = p; + for (int i = 1; i < minWidth; ++i) + { + pow2Table[i] = pow2Table[i - 1].timesPow2(d); + } + + c.normalizeAll(pow2Table); + + lookupTable = new ECPoint[n]; + lookupTable[0] = c.getInfinity(); + + for (int bit = minWidth - 1; bit >= 0; --bit) + { + ECPoint pow2 = pow2Table[bit]; + + int step = 1 << bit; + for (int i = step; i < n; i += (step << 1)) + { + lookupTable[i] = lookupTable[i - step].add(pow2); + } + } + + c.normalizeAll(lookupTable); + + info.setPreComp(lookupTable); + info.setWidth(minWidth); + + c.setPreCompInfo(p, PRECOMP_NAME, info); + } + + return info; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java new file mode 100644 index 000000000..fb2c3ee32 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/GLVMultiplier.java @@ -0,0 +1,42 @@ +package org.spongycastle.math.ec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.endo.GLVEndomorphism; + +public class GLVMultiplier extends AbstractECMultiplier +{ + protected final ECCurve curve; + protected final GLVEndomorphism glvEndomorphism; + + public GLVMultiplier(ECCurve curve, GLVEndomorphism glvEndomorphism) + { + if (curve == null || curve.getOrder() == null) + { + throw new IllegalArgumentException("Need curve with known group order"); + } + + this.curve = curve; + this.glvEndomorphism = glvEndomorphism; + } + + protected ECPoint multiplyPositive(ECPoint p, BigInteger k) + { + if (!curve.equals(p.getCurve())) + { + throw new IllegalStateException(); + } + + BigInteger n = p.getCurve().getOrder(); + BigInteger[] ab = glvEndomorphism.decomposeScalar(k.mod(n)); + BigInteger a = ab[0], b = ab[1]; + + ECPointMap pointMap = glvEndomorphism.getPointMap(); + if (glvEndomorphism.hasEfficientPointMap()) + { + return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap, b); + } + + return ECAlgorithms.implShamirsTrickWNaf(p, a, pointMap.map(p), b); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/IntArray.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/IntArray.java deleted file mode 100644 index f86cfbc16..000000000 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/IntArray.java +++ /dev/null @@ -1,860 +0,0 @@ -package org.spongycastle.math.ec; - -import org.spongycastle.util.Arrays; - -import java.math.BigInteger; - -class IntArray -{ -// private static int DEINTERLEAVE_MASK = 0x55555555; - - /* - * This expands 8 bit indices into 16 bit contents, by inserting 0s between bits. - * In a binary field, this operation is the same as squaring an 8 bit number. - */ - private static final int[] INTERLEAVE_TABLE = new int[] { 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, - 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, - 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, 0x0400, 0x0401, 0x0404, - 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500, - 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, - 0x0555, 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, - 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144, - 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440, - 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, - 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, - 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104, - 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, 0x4400, - 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, - 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, - 0x4551, 0x4554, 0x4555, 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044, - 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140, - 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, - 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, - 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 }; - - // For toString(); must have length 32 - private static final String ZEROES = "00000000000000000000000000000000"; - - private final static byte[] bitLengths = - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 - }; - - public static int getWordLength(int bits) - { - return (bits + 31) >>> 5; - } - - // TODO make m fixed for the IntArray, and hence compute T once and for all - - private int[] m_ints; - - public IntArray(int intLen) - { - m_ints = new int[intLen]; - } - - public IntArray(int[] ints) - { - m_ints = ints; - } - - public IntArray(BigInteger bigInt) - { - if (bigInt == null || bigInt.signum() < 0) - { - throw new IllegalArgumentException("invalid F2m field value"); - } - - if (bigInt.signum() == 0) - { - m_ints = new int[] { 0 }; - return; - } - - byte[] barr = bigInt.toByteArray(); - int barrLen = barr.length; - int barrStart = 0; - if (barr[0] == 0) - { - // First byte is 0 to enforce highest (=sign) bit is zero. - // In this case ignore barr[0]. - barrLen--; - barrStart = 1; - } - int intLen = (barrLen + 3) / 4; - m_ints = new int[intLen]; - - int iarrJ = intLen - 1; - int rem = barrLen % 4 + barrStart; - int temp = 0; - int barrI = barrStart; - if (barrStart < rem) - { - for (; barrI < rem; barrI++) - { - temp <<= 8; - int barrBarrI = barr[barrI] & 0xFF; - temp |= barrBarrI; - } - m_ints[iarrJ--] = temp; - } - - for (; iarrJ >= 0; iarrJ--) - { - temp = 0; - for (int i = 0; i < 4; i++) - { - temp <<= 8; - int barrBarrI = barr[barrI++] & 0xFF; - temp |= barrBarrI; - } - m_ints[iarrJ] = temp; - } - } - - public boolean isZero() - { - int[] a = m_ints; - for (int i = 0; i < a.length; ++i) - { - if (a[i] != 0) - { - return false; - } - } - return true; - } - - public int getUsedLength() - { - return getUsedLengthFrom(m_ints.length); - } - - public int getUsedLengthFrom(int from) - { - int[] a = m_ints; - from = Math.min(from, a.length); - - if (from < 1) - { - return 0; - } - - // Check if first element will act as sentinel - if (a[0] != 0) - { - while (a[--from] == 0) - { - } - return from + 1; - } - - do - { - if (a[--from] != 0) - { - return from + 1; - } - } - while (from > 0); - - return 0; - } - - public int degree() - { - int i = m_ints.length, w; - do - { - if (i == 0) - { - return 0; - } - w = m_ints[--i]; - } - while (w == 0); - - return (i << 5) + bitLength(w); - } - - private static int bitLength(int w) - { - int t = w >>> 16; - if (t == 0) - { - t = w >>> 8; - return (t == 0) ? bitLengths[w] : 8 + bitLengths[t]; - } - - int u = t >>> 8; - return (u == 0) ? 16 + bitLengths[t] : 24 + bitLengths[u]; - } - - private int[] resizedInts(int newLen) - { - int[] newInts = new int[newLen]; - System.arraycopy(m_ints, 0, newInts, 0, Math.min(m_ints.length, newLen)); - return newInts; - } - - public BigInteger toBigInteger() - { - int usedLen = getUsedLength(); - if (usedLen == 0) - { - return ECConstants.ZERO; - } - - int highestInt = m_ints[usedLen - 1]; - byte[] temp = new byte[4]; - int barrI = 0; - boolean trailingZeroBytesDone = false; - for (int j = 3; j >= 0; j--) - { - byte thisByte = (byte) (highestInt >>> (8 * j)); - if (trailingZeroBytesDone || (thisByte != 0)) - { - trailingZeroBytesDone = true; - temp[barrI++] = thisByte; - } - } - - int barrLen = 4 * (usedLen - 1) + barrI; - byte[] barr = new byte[barrLen]; - for (int j = 0; j < barrI; j++) - { - barr[j] = temp[j]; - } - // Highest value int is done now - - for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) - { - for (int j = 3; j >= 0; j--) - { - barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j)); - } - } - return new BigInteger(1, barr); - } - - private static int shiftLeft(int[] x, int count) - { - int prev = 0; - for (int i = 0; i < count; ++i) - { - int next = x[i]; - x[i] = (next << 1) | prev; - prev = next >>> 31; - } - return prev; - } - - public void addOneShifted(int shift) - { - if (shift >= m_ints.length) - { - m_ints = resizedInts(shift + 1); - } - - m_ints[shift] ^= 1; - } - - private void addShiftedByBits(IntArray other, int bits) - { - int words = bits >>> 5; - int shift = bits & 0x1F; - - if (shift == 0) - { - addShiftedByWords(other, words); - return; - } - - int otherUsedLen = other.getUsedLength(); - if (otherUsedLen == 0) - { - return; - } - - int minLen = otherUsedLen + words + 1; - if (minLen > m_ints.length) - { - m_ints = resizedInts(minLen); - } - - int shiftInv = 32 - shift, prev = 0; - for (int i = 0; i < otherUsedLen; ++i) - { - int next = other.m_ints[i]; - m_ints[i + words] ^= (next << shift) | prev; - prev = next >>> shiftInv; - } - m_ints[otherUsedLen + words] ^= prev; - } - - private static int addShiftedByBits(int[] x, int[] y, int count, int shift) - { - int shiftInv = 32 - shift, prev = 0; - for (int i = 0; i < count; ++i) - { - int next = y[i]; - x[i] ^= (next << shift) | prev; - prev = next >>> shiftInv; - } - return prev; - } - - private static int addShiftedByBits(int[] x, int xOff, int[] y, int yOff, int count, int shift) - { - int shiftInv = 32 - shift, prev = 0; - for (int i = 0; i < count; ++i) - { - int next = y[yOff + i]; - x[xOff + i] ^= (next << shift) | prev; - prev = next >>> shiftInv; - } - return prev; - } - - public void addShiftedByWords(IntArray other, int words) - { - int otherUsedLen = other.getUsedLength(); - if (otherUsedLen == 0) - { - return; - } - - int minLen = otherUsedLen + words; - if (minLen > m_ints.length) - { - m_ints = resizedInts(minLen); - } - - for (int i = 0; i < otherUsedLen; i++) - { - m_ints[words + i] ^= other.m_ints[i]; - } - } - - private static void addShiftedByWords(int[] x, int xOff, int[] y, int count) - { - for (int i = 0; i < count; ++i) - { - x[xOff + i] ^= y[i]; - } - } - - private static void add(int[] x, int[] y, int count) - { - for (int i = 0; i < count; ++i) - { - x[i] ^= y[i]; - } - } - - private static void distribute(int[] x, int dst1, int dst2, int src, int count) - { - for (int i = 0; i < count; ++i) - { - int v = x[src + i]; - x[dst1 + i] ^= v; - x[dst2 + i] ^= v; - } - } - - public int getLength() - { - return m_ints.length; - } - - public void flipWord(int bit, int word) - { - int len = m_ints.length; - int n = bit >>> 5; - if (n < len) - { - int shift = bit & 0x1F; - if (shift == 0) - { - m_ints[n] ^= word; - } - else - { - m_ints[n] ^= word << shift; - if (++n < len) - { - m_ints[n] ^= word >>> (32 - shift); - } - } - } - } - - public int getWord(int bit) - { - int len = m_ints.length; - int n = bit >>> 5; - if (n >= len) - { - return 0; - } - int shift = bit & 0x1F; - if (shift == 0) - { - return m_ints[n]; - } - int result = m_ints[n] >>> shift; - if (++n < len) - { - result |= m_ints[n] << (32 - shift); - } - return result; - } - - public boolean testBitZero() - { - return m_ints.length > 0 && (m_ints[0] & 1) != 0; - } - - public boolean testBit(int n) - { - // theInt = n / 32 - int theInt = n >>> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int tester = 1 << theBit; - return ((m_ints[theInt] & tester) != 0); - } - - public void flipBit(int n) - { - // theInt = n / 32 - int theInt = n >>> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int flipper = 1 << theBit; - m_ints[theInt] ^= flipper; - } - - public void setBit(int n) - { - // theInt = n / 32 - int theInt = n >>> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int setter = 1 << theBit; - m_ints[theInt] |= setter; - } - - public void clearBit(int n) - { - // theInt = n / 32 - int theInt = n >>> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int setter = 1 << theBit; - m_ints[theInt] &= ~setter; - } - - public IntArray multiply(IntArray other, int m) - { - int aLen = getUsedLength(); - if (aLen == 0) - { - return new IntArray(1); - } - - int bLen = other.getUsedLength(); - if (bLen == 0) - { - return new IntArray(1); - } - - IntArray A = this, B = other; - if (aLen > bLen) - { - A = other; B = this; - int tmp = aLen; aLen = bLen; bLen = tmp; - } - - if (aLen == 1) - { - int a = A.m_ints[0]; - int[] b = B.m_ints; - int[] c = new int[aLen + bLen]; - if ((a & 1) != 0) - { - add(c, b, bLen); - } - int k = 1; - while ((a >>>= 1) != 0) - { - if ((a & 1) != 0) - { - addShiftedByBits(c, b, bLen, k); - } - ++k; - } - return new IntArray(c); - } - - // TODO It'd be better to be able to tune the width directly (need support for interleaving arbitrary widths) - int complexity = aLen <= 8 ? 1 : 2; - - int width = 1 << complexity; - int shifts = (32 >>> complexity); - - int bExt = bLen; - if ((B.m_ints[bLen - 1] >>> (33 - shifts)) != 0) - { - ++bExt; - } - - int cLen = bExt + aLen; - - int[] c = new int[cLen << width]; - System.arraycopy(B.m_ints, 0, c, 0, bLen); - interleave(A.m_ints, 0, c, bExt, aLen, complexity); - - int[] ci = new int[1 << width]; - for (int i = 1; i < ci.length; ++i) - { - ci[i] = ci[i - 1] + cLen; - } - - int MASK = (1 << width) - 1; - - int k = 0; - for (;;) - { - for (int aPos = 0; aPos < aLen; ++aPos) - { - int index = (c[bExt + aPos] >>> k) & MASK; - if (index != 0) - { - addShiftedByWords(c, aPos + ci[index], c, bExt); - } - } - - if ((k += width) >= 32) - { - break; - } - - shiftLeft(c, bExt); - } - - int ciPos = ci.length, pow2 = ciPos >>> 1, offset = 32; - while (--ciPos > 1) - { - if (ciPos == pow2) - { - offset -= shifts; - addShiftedByBits(c, ci[1], c, ci[pow2], cLen, offset); - pow2 >>>= 1; - } - else - { - distribute(c, ci[pow2], ci[ciPos - pow2], ci[ciPos], cLen); - } - } - - // TODO reduce in place to avoid extra copying - IntArray p = new IntArray(cLen); - System.arraycopy(c, ci[1], p.m_ints, 0, cLen); - return p; - } - -// private static void deInterleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds) -// { -// for (int i = 0; i < count; ++i) -// { -// z[zOff + i] = deInterleave(x[zOff + i], rounds); -// } -// } -// -// private static int deInterleave(int x, int rounds) -// { -// while (--rounds >= 0) -// { -// x = deInterleave16(x & DEINTERLEAVE_MASK) | (deInterleave16((x >>> 1) & DEINTERLEAVE_MASK) << 16); -// } -// return x; -// } -// -// private static int deInterleave16(int x) -// { -// x = (x | (x >>> 1)) & 0x33333333; -// x = (x | (x >>> 2)) & 0x0F0F0F0F; -// x = (x | (x >>> 4)) & 0x00FF00FF; -// x = (x | (x >>> 8)) & 0x0000FFFF; -// return x; -// } - - public void reduce(int m, int[] ks) - { - int len = getUsedLength(); - int mLen = (m + 31) >>> 5; - if (len < mLen) - { - return; - } - - int _2m = m << 1; - int pos = Math.min(_2m - 2, (len << 5) - 1); - - int kMax = ks[ks.length - 1]; - if (kMax < m - 31) - { - reduceWordWise(pos, m, ks); - } - else - { - reduceBitWise(pos, m, ks); - } - - // Instead of flipping the high bits in the loop, explicitly clear any partial word above m bits - int partial = m & 0x1F; - if (partial != 0) - { - m_ints[mLen - 1] &= (1 << partial) - 1; - } - - if (len > mLen) - { - m_ints = resizedInts(mLen); - } - } - - private void reduceBitWise(int from, int m, int[] ks) - { - for (int i = from; i >= m; --i) - { - if (testBit(i)) - { -// clearBit(i); - int bit = i - m; - flipBit(bit); - int j = ks.length; - while (--j >= 0) - { - flipBit(ks[j] + bit); - } - } - } - } - - private void reduceWordWise(int from, int m, int[] ks) - { - int pos = m + ((from - m) & ~0x1F); - for (int i = pos; i >= m; i -= 32) - { - int word = getWord(i); - if (word != 0) - { -// flipWord(i); - int bit = i - m; - flipWord(bit, word); - int j = ks.length; - while (--j >= 0) - { - flipWord(ks[j] + bit, word); - } - } - } - } - - public IntArray square(int m) - { - int len = getUsedLength(); - if (len == 0) - { - return this; - } - - int _2len = len << 1; - int[] r = new int[_2len]; - - int pos = 0; - while (pos < _2len) - { - int mi = m_ints[pos >>> 1]; - r[pos++] = interleave16(mi & 0xFFFF); - r[pos++] = interleave16(mi >>> 16); - } - - return new IntArray(r); - } - - private static void interleave(int[] x, int xOff, int[] z, int zOff, int count, int rounds) - { - for (int i = 0; i < count; ++i) - { - z[zOff + i] = interleave(x[xOff + i], rounds); - } - } - - private static int interleave(int x, int rounds) - { - while (--rounds >= 0) - { - x = interleave16(x & 0xFFFF) | (interleave16(x >>> 16) << 1); - } - return x; - } - - private static int interleave16(int n) - { - return INTERLEAVE_TABLE[n & 0xFF] | INTERLEAVE_TABLE[n >>> 8] << 16; - } - - public IntArray modInverse(int m, int[] ks) - { - // Inversion in F2m using the extended Euclidean algorithm - // Input: A nonzero polynomial a(z) of degree at most m-1 - // Output: a(z)^(-1) mod f(z) - - int uzDegree = degree(); - if (uzDegree == 1) - { - return this; - } - - // u(z) := a(z) - IntArray uz = (IntArray)clone(); - - int t = getWordLength(m); - - // v(z) := f(z) - IntArray vz = new IntArray(t); - vz.setBit(m); - vz.setBit(0); - vz.setBit(ks[0]); - if (ks.length > 1) - { - vz.setBit(ks[1]); - vz.setBit(ks[2]); - } - - // g1(z) := 1, g2(z) := 0 - IntArray g1z = new IntArray(t); - g1z.setBit(0); - IntArray g2z = new IntArray(t); - - while (uzDegree != 0) - { - // j := deg(u(z)) - deg(v(z)) - int j = uzDegree - vz.degree(); - - // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j - if (j < 0) - { - final IntArray uzCopy = uz; - uz = vz; - vz = uzCopy; - - final IntArray g1zCopy = g1z; - g1z = g2z; - g2z = g1zCopy; - - j = -j; - } - - // u(z) := u(z) + z^j * v(z) - // Note, that no reduction modulo f(z) is required, because - // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) - // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) - // = deg(u(z)) - // uz = uz.xor(vz.shiftLeft(j)); - uz.addShiftedByBits(vz, j); - uzDegree = uz.degree(); - - // g1(z) := g1(z) + z^j * g2(z) -// g1z = g1z.xor(g2z.shiftLeft(j)); - if (uzDegree != 0) - { - g1z.addShiftedByBits(g2z, j); - } - } - return g2z; - } - - public boolean equals(Object o) - { - if (!(o instanceof IntArray)) - { - return false; - } - IntArray other = (IntArray) o; - int usedLen = getUsedLength(); - if (other.getUsedLength() != usedLen) - { - return false; - } - for (int i = 0; i < usedLen; i++) - { - if (m_ints[i] != other.m_ints[i]) - { - return false; - } - } - return true; - } - - public int hashCode() - { - int usedLen = getUsedLength(); - int hash = 1; - for (int i = 0; i < usedLen; i++) - { - hash *= 31; - hash ^= m_ints[i]; - } - return hash; - } - - public Object clone() - { - return new IntArray(Arrays.clone(m_ints)); - } - - public String toString() - { - int i = getUsedLength(); - if (i == 0) - { - return "0"; - } - - StringBuffer sb = new StringBuffer(Integer.toBinaryString(m_ints[--i])); - while (--i >= 0) - { - String s = Integer.toBinaryString(m_ints[i]); - - // Add leading zeroes, except for highest significant word - int len = s.length(); - if (len < 32) - { - sb.append(ZEROES.substring(len)); - } - - sb.append(s); - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/LongArray.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/LongArray.java index 21b2e45d2..6f718cd59 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/LongArray.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/LongArray.java @@ -371,6 +371,23 @@ class LongArray } } + public boolean isOne() + { + long[] a = m_ints; + if (a[0] != 1L) + { + return false; + } + for (int i = 1; i < a.length; ++i) + { + if (a[i] != 0L) + { + return false; + } + } + return true; + } + public boolean isZero() { long[] a = m_ints; @@ -822,12 +839,12 @@ class LongArray add(c, cOff, b, 0, bLen); } int k = 1; - while ((a >>>= 1) != 0) + while ((a >>>= 1) != 0L) { if ((a & 1L) != 0L) { long carry = addShiftedUp(c, cOff, b, 0, bLen, k); - if (carry != 0) + if (carry != 0L) { c[cOff + bLen] ^= carry; } @@ -871,8 +888,8 @@ class LongArray if (aLen == 1) { - long a = A.m_ints[0]; - if (a == 1L) + long a0 = A.m_ints[0]; + if (a0 == 1L) { return B; } @@ -880,13 +897,13 @@ class LongArray /* * Fast path for small A, with performance dependent only on the number of set bits */ - long[] c = new long[cLen]; - multiplyWord(a, B.m_ints, bLen, c, 0); + long[] c0 = new long[cLen]; + multiplyWord(a0, B.m_ints, bLen, c0, 0); /* * Reduce the raw answer against the reduction coefficients */ - return reduceResult(c, 0, cLen, m, ks); + return reduceResult(c0, 0, cLen, m, ks); } /* @@ -1003,8 +1020,8 @@ class LongArray if (aLen == 1) { - long a = A.m_ints[0]; - if (a == 1L) + long a0 = A.m_ints[0]; + if (a0 == 1L) { return B; } @@ -1012,13 +1029,13 @@ class LongArray /* * Fast path for small A, with performance dependent only on the number of set bits */ - long[] c = new long[cLen]; - multiplyWord(a, B.m_ints, bLen, c, 0); + long[] c0 = new long[cLen]; + multiplyWord(a0, B.m_ints, bLen, c0, 0); /* * Reduce the raw answer against the reduction coefficients */ - return reduceResult(c, 0, cLen, m, ks); + return reduceResult(c0, 0, cLen, m, ks); } /* @@ -1077,7 +1094,8 @@ class LongArray aVal >>>= 4; int v = (int)aVal & MASK; addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax); - if ((aVal >>>= 4) == 0L) + aVal >>>= 4; + if (aVal == 0L) { break; } @@ -1085,10 +1103,12 @@ class LongArray } } - int cOff = c.length; - while ((cOff -= cLen) != 0) { - addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8); + int cOff = c.length; + while ((cOff -= cLen) != 0) + { + addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8); + } } /* @@ -1132,8 +1152,8 @@ class LongArray if (aLen == 1) { - long a = A.m_ints[0]; - if (a == 1L) + long a0 = A.m_ints[0]; + if (a0 == 1L) { return B; } @@ -1141,13 +1161,13 @@ class LongArray /* * Fast path for small A, with performance dependent only on the number of set bits */ - long[] c = new long[cLen]; - multiplyWord(a, B.m_ints, bLen, c, 0); + long[] c0 = new long[cLen]; + multiplyWord(a0, B.m_ints, bLen, c0, 0); /* * Reduce the raw answer against the reduction coefficients */ - return reduceResult(c, 0, cLen, m, ks); + return reduceResult(c0, 0, cLen, m, ks); } // NOTE: This works, but is slower than width 4 processing @@ -1314,6 +1334,158 @@ class LongArray return reduceResult(c, ci[1], cLen, m, ks); } + public LongArray modReduce(int m, int[] ks) + { + long[] buf = Arrays.clone(m_ints); + int rLen = reduceInPlace(buf, 0, buf.length, m, ks); + return new LongArray(buf, 0, rLen); + } + + public LongArray multiply(LongArray other, int m, int[] ks) + { + /* + * Find out the degree of each argument and handle the zero cases + */ + int aDeg = degree(); + if (aDeg == 0) + { + return this; + } + int bDeg = other.degree(); + if (bDeg == 0) + { + return other; + } + + /* + * Swap if necessary so that A is the smaller argument + */ + LongArray A = this, B = other; + if (aDeg > bDeg) + { + A = other; B = this; + int tmp = aDeg; aDeg = bDeg; bDeg = tmp; + } + + /* + * Establish the word lengths of the arguments and result + */ + int aLen = (aDeg + 63) >>> 6; + int bLen = (bDeg + 63) >>> 6; + int cLen = (aDeg + bDeg + 62) >>> 6; + + if (aLen == 1) + { + long a0 = A.m_ints[0]; + if (a0 == 1L) + { + return B; + } + + /* + * Fast path for small A, with performance dependent only on the number of set bits + */ + long[] c0 = new long[cLen]; + multiplyWord(a0, B.m_ints, bLen, c0, 0); + + /* + * Reduce the raw answer against the reduction coefficients + */ +// return reduceResult(c0, 0, cLen, m, ks); + return new LongArray(c0, 0, cLen); + } + + /* + * Determine if B will get bigger during shifting + */ + int bMax = (bDeg + 7 + 63) >>> 6; + + /* + * Lookup table for the offset of each B in the tables + */ + int[] ti = new int[16]; + + /* + * Precompute table of all 4-bit products of B + */ + long[] T0 = new long[bMax << 4]; + int tOff = bMax; + ti[1] = tOff; + System.arraycopy(B.m_ints, 0, T0, tOff, bLen); + for (int i = 2; i < 16; ++i) + { + ti[i] = (tOff += bMax); + if ((i & 1) == 0) + { + shiftUp(T0, tOff >>> 1, T0, tOff, bMax, 1); + } + else + { + add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax); + } + } + + /* + * Second table with all 4-bit products of B shifted 4 bits + */ + long[] T1 = new long[T0.length]; + shiftUp(T0, 0, T1, 0, T0.length, 4); +// shiftUp(T0, bMax, T1, bMax, tOff, 4); + + long[] a = A.m_ints; + long[] c = new long[cLen << 3]; + + int MASK = 0xF; + + /* + * Lopez-Dahab (Modified) algorithm + */ + + for (int aPos = 0; aPos < aLen; ++aPos) + { + long aVal = a[aPos]; + int cOff = aPos; + for (;;) + { + int u = (int)aVal & MASK; + aVal >>>= 4; + int v = (int)aVal & MASK; + addBoth(c, cOff, T0, ti[u], T1, ti[v], bMax); + aVal >>>= 4; + if (aVal == 0L) + { + break; + } + cOff += cLen; + } + } + + { + int cOff = c.length; + while ((cOff -= cLen) != 0) + { + addShiftedUp(c, cOff - cLen, c, cOff, cLen, 8); + } + } + + /* + * Finally the raw answer is collected, reduce it against the reduction coefficients + */ +// return reduceResult(c, 0, cLen, m, ks); + return new LongArray(c, 0, cLen); + } + + public void reduce(int m, int[] ks) + { + long[] buf = m_ints; + int rLen = reduceInPlace(buf, 0, buf.length, m, ks); + if (rLen < buf.length) + { + m_ints = new long[rLen]; + System.arraycopy(buf, 0, m_ints, 0, rLen); + } + } + private static LongArray reduceResult(long[] buf, int off, int len, int m, int[] ks) { int rLen = reduceInPlace(buf, off, len, m, ks); @@ -1405,13 +1577,13 @@ class LongArray private static void reduceBit(long[] buf, int off, int bit, int m, int[] ks) { flipBit(buf, off, bit); - int base = bit - m; + int n = bit - m; int j = ks.length; while (--j >= 0) { - flipBit(buf, off, ks[j] + base); + flipBit(buf, off, ks[j] + n); } - flipBit(buf, off, base); + flipBit(buf, off, n); } private static void reduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks) @@ -1428,12 +1600,14 @@ class LongArray } } - int partial = toBit & 0x3F; - long word = buf[off + toPos] >>> partial; - if (word != 0) { - buf[off + toPos] ^= word << partial; - reduceWord(buf, off, toBit, word, m, ks); + int partial = toBit & 0x3F; + long word = buf[off + toPos] >>> partial; + if (word != 0) + { + buf[off + toPos] ^= word << partial; + reduceWord(buf, off, toBit, word, m, ks); + } } } @@ -1502,37 +1676,59 @@ class LongArray return new LongArray(r, 0, reduceInPlace(r, 0, r.length, m, ks)); } -// private LongArray modSquareN(int n, int m, int[] ks) -// { -// int len = getUsedLength(); -// if (len == 0) -// { -// return this; -// } -// -// int mLen = (m + 63) >>> 6; -// long[] r = new long[mLen << 1]; -// System.arraycopy(m_ints, 0, r, 0, len); -// -// while (--n >= 0) -// { -// squareInPlace(r, len, m, ks); -// len = reduceInPlace(r, 0, r.length, m, ks); -// } -// -// return new LongArray(r, 0, len); -// } -// -// private static void squareInPlace(long[] x, int xLen, int m, int[] ks) -// { -// int pos = xLen << 1; -// while (--xLen >= 0) -// { -// long xVal = x[xLen]; -// x[--pos] = interleave2_32to64((int)(xVal >>> 32)); -// x[--pos] = interleave2_32to64((int)xVal); -// } -// } + public LongArray modSquareN(int n, int m, int[] ks) + { + int len = getUsedLength(); + if (len == 0) + { + return this; + } + + int mLen = (m + 63) >>> 6; + long[] r = new long[mLen << 1]; + System.arraycopy(m_ints, 0, r, 0, len); + + while (--n >= 0) + { + squareInPlace(r, len, m, ks); + len = reduceInPlace(r, 0, r.length, m, ks); + } + + return new LongArray(r, 0, len); + } + + public LongArray square(int m, int[] ks) + { + int len = getUsedLength(); + if (len == 0) + { + return this; + } + + int _2len = len << 1; + long[] r = new long[_2len]; + + int pos = 0; + while (pos < _2len) + { + long mi = m_ints[pos >>> 1]; + r[pos++] = interleave2_32to64((int)mi); + r[pos++] = interleave2_32to64((int)(mi >>> 32)); + } + + return new LongArray(r, 0, r.length); + } + + private static void squareInPlace(long[] x, int xLen, int m, int[] ks) + { + int pos = xLen << 1; + while (--xLen >= 0) + { + long xVal = x[xLen]; + x[--pos] = interleave2_32to64((int)(xVal >>> 32)); + x[--pos] = interleave2_32to64((int)xVal); + } + } private static void interleave(long[] x, int xOff, long[] z, int zOff, int count, int width) { @@ -1856,6 +2052,10 @@ class LongArray * Output: a(z)^(-1) mod f(z) */ int uzDegree = degree(); + if (uzDegree == 0) + { + throw new IllegalStateException(); + } if (uzDegree == 1) { return this; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java index 6c03173f9..b4c53fdde 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ReferenceMultiplier.java @@ -4,34 +4,8 @@ import java.math.BigInteger; public class ReferenceMultiplier extends AbstractECMultiplier { - /** - * Simple shift-and-add multiplication. Serves as reference implementation - * to verify (possibly faster) implementations in - * {@link org.spongycastle.math.ec.ECPoint ECPoint}. - * - * @param p The point to multiply. - * @param k The factor by which to multiply. - * @return The result of the point multiplicationk * p
. - */ protected ECPoint multiplyPositive(ECPoint p, BigInteger k) { - ECPoint q = p.getCurve().getInfinity(); - int t = k.bitLength(); - if (t > 0) - { - if (k.testBit(0)) - { - q = p; - } - for (int i = 1; i < t; i++) - { - p = p.twice(); - if (k.testBit(i)) - { - q = q.add(p); - } - } - } - return q; + return ECAlgorithms.referenceMultiply(p, k); } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java new file mode 100644 index 000000000..6630c4f94 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleXPointMap.java @@ -0,0 +1,16 @@ +package org.spongycastle.math.ec; + +public class ScaleXPointMap implements ECPointMap +{ + protected final ECFieldElement scale; + + public ScaleXPointMap(ECFieldElement scale) + { + this.scale = scale; + } + + public ECPoint map(ECPoint p) + { + return p.scaleX(scale); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java new file mode 100644 index 000000000..7a215cb44 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/ScaleYPointMap.java @@ -0,0 +1,16 @@ +package org.spongycastle.math.ec; + +public class ScaleYPointMap implements ECPointMap +{ + protected final ECFieldElement scale; + + public ScaleYPointMap(ECFieldElement scale) + { + this.scale = scale; + } + + public ECPoint map(ECPoint p) + { + return p.scaleY(scale); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java index f882abc63..c367830aa 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/SimpleBigDecimal.java @@ -54,12 +54,6 @@ class SimpleBigDecimal this.scale = scale; } - private SimpleBigDecimal(SimpleBigDecimal limBigDec) - { - bigInt = limBigDec.bigInt; - scale = limBigDec.scale; - } - private void checkScale(SimpleBigDecimal b) { if (scale != b.scale) @@ -78,7 +72,7 @@ class SimpleBigDecimal if (newScale == scale) { - return new SimpleBigDecimal(this); + return this; } return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale), diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/Tnaf.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/Tnaf.java index 6c5a0db56..d5aba3209 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/Tnaf.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/Tnaf.java @@ -535,45 +535,36 @@ class Tnaf int m = curve.getM(); int a = curve.getA().toBigInteger().intValue(); byte mu = curve.getMu(); - int h = curve.getH().intValue(); + int shifts = getShiftsForCofactor(curve.getCofactor()); int index = m + 3 - a; BigInteger[] ui = getLucas(mu, index, false); - - BigInteger dividend0; - BigInteger dividend1; if (mu == 1) { - dividend0 = ECConstants.ONE.subtract(ui[1]); - dividend1 = ECConstants.ONE.subtract(ui[0]); - } - else if (mu == -1) - { - dividend0 = ECConstants.ONE.add(ui[1]); - dividend1 = ECConstants.ONE.add(ui[0]); - } - else - { - throw new IllegalArgumentException("mu must be 1 or -1"); + ui[0] = ui[0].negate(); + ui[1] = ui[1].negate(); } - BigInteger[] si = new BigInteger[2]; + BigInteger dividend0 = ECConstants.ONE.add(ui[1]).shiftRight(shifts); + BigInteger dividend1 = ECConstants.ONE.add(ui[0]).shiftRight(shifts).negate(); - if (h == 2) + return new BigInteger[] { dividend0, dividend1 }; + } + + protected static int getShiftsForCofactor(BigInteger h) + { + if (h != null) { - si[0] = dividend0.shiftRight(1); - si[1] = dividend1.shiftRight(1).negate(); - } - else if (h == 4) - { - si[0] = dividend0.shiftRight(2); - si[1] = dividend1.shiftRight(2).negate(); - } - else - { - throw new IllegalArgumentException("h (Cofactor) must be 2 or 4"); + if (h.equals(ECConstants.TWO)) + { + return 1; + } + if (h.equals(ECConstants.FOUR)) + { + return 2; + } } - return si; + throw new IllegalArgumentException("h (Cofactor) must be 2 or 4"); } /** diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java index 0f64450b7..b9af4da95 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafL2RMultiplier.java @@ -31,7 +31,7 @@ public class WNafL2RMultiplier extends AbstractECMultiplier int i = wnaf.length; /* - * NOTE This code optimizes the first window using the precomputed points to substitute an + * NOTE: We try to optimize the first window using the precomputed points to substitute an * addition for 2 or more doublings. */ if (i > 1) @@ -42,19 +42,14 @@ public class WNafL2RMultiplier extends AbstractECMultiplier int n = Math.abs(digit); ECPoint[] table = digit < 0 ? preCompNeg : preComp; - /* - * NOTE: We use this optimization conservatively, since some coordinate systems have - * significantly cheaper doubling relative to addition. - * - * (n << 2) selects precomputed values in the lower half of the table - * (n << 3) selects precomputed values in the lower quarter of the table - */ - //if ((n << 2) < (1 << width)) - if ((n << 3) < (1 << width)) + // Optimization can only be used for values in the lower half of the table + if ((n << 2) < (1 << width)) { int highest = LongArray.bitLengths[n]; - int lowBits = n ^ (1 << (highest - 1)); + + // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting? int scale = width - highest; + int lowBits = n ^ (1 << (highest - 1)); int i1 = ((1 << (width - 1)) - 1); int i2 = (lowBits << scale) + 1; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java index 4a7b7e31c..2eaea9400 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafPreCompInfo.java @@ -10,47 +10,47 @@ public class WNafPreCompInfo implements PreCompInfo * Array holding the precomputedECPoint
s used for a Window * NAF multiplication. */ - private ECPoint[] preComp = null; + protected ECPoint[] preComp = null; /** * Array holding the negations of the precomputedECPoint
s used * for a Window NAF multiplication. */ - private ECPoint[] preCompNeg = null; + protected ECPoint[] preCompNeg = null; /** * Holds anECPoint
representing twice(this). Used for the * Window NAF multiplication to create or extend the precomputed values. */ - private ECPoint twiceP = null; + protected ECPoint twice = null; - protected ECPoint[] getPreComp() + public ECPoint[] getPreComp() { return preComp; } - protected ECPoint[] getPreCompNeg() - { - return preCompNeg; - } - - protected void setPreComp(ECPoint[] preComp) + public void setPreComp(ECPoint[] preComp) { this.preComp = preComp; } - protected void setPreCompNeg(ECPoint[] preCompNeg) + public ECPoint[] getPreCompNeg() + { + return preCompNeg; + } + + public void setPreCompNeg(ECPoint[] preCompNeg) { this.preCompNeg = preCompNeg; } - protected ECPoint getTwiceP() + public ECPoint getTwice() { - return twiceP; + return twice; } - protected void setTwiceP(ECPoint twiceP) + public void setTwice(ECPoint twice) { - this.twiceP = twiceP; + this.twice = twice; } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java index 9215f9490..4e0c5869b 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WNafUtil.java @@ -4,7 +4,12 @@ import java.math.BigInteger; public abstract class WNafUtil { - private static int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 }; + public static final String PRECOMP_NAME = "bc_wnaf"; + + private static final int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 }; + + private static final byte[] EMPTY_BYTES = new byte[0]; + private static final int[] EMPTY_INTS = new int[0]; public static int[] generateCompactNaf(BigInteger k) { @@ -12,30 +17,35 @@ public abstract class WNafUtil { throw new IllegalArgumentException("'k' must have bitlength < 2^16"); } + if (k.signum() == 0) + { + return EMPTY_INTS; + } BigInteger _3k = k.shiftLeft(1).add(k); - int digits = _3k.bitLength() - 1; - int[] naf = new int[(digits + 1) >> 1]; + int bits = _3k.bitLength(); + int[] naf = new int[bits >> 1]; - int length = 0, zeroes = 0; - for (int i = 1; i <= digits; ++i) + BigInteger diff = _3k.xor(k); + + int highBit = bits - 1, length = 0, zeroes = 0; + for (int i = 1; i < highBit; ++i) { - boolean _3kBit = _3k.testBit(i); - boolean kBit = k.testBit(i); - - if (_3kBit == kBit) + if (!diff.testBit(i)) { ++zeroes; + continue; } - else - { - int digit = kBit ? -1 : 1; - naf[length++] = (digit << 16) | zeroes; - zeroes = 0; - } + + int digit = k.testBit(i) ? -1 : 1; + naf[length++] = (digit << 16) | zeroes; + zeroes = 1; + ++i; } + naf[length++] = (1 << 16) | zeroes; + if (naf.length > length) { naf = trim(naf, length); @@ -59,6 +69,10 @@ public abstract class WNafUtil { throw new IllegalArgumentException("'k' must have bitlength < 2^16"); } + if (k.signum() == 0) + { + return EMPTY_INTS; + } int[] wnaf = new int[k.bitLength() / width + 1]; @@ -114,9 +128,10 @@ public abstract class WNafUtil BigInteger k0 = g, k1 = h; int j = 0, d0 = 0, d1 = 0; - while (k0.signum() > 0 || k1.signum() > 0 || d0 > 0 || d1 > 0) + int offset = 0; + while ((d0 | d1) != 0 || k0.bitLength() > offset || k1.bitLength() > offset) { - int n0 = (k0.intValue() + d0) & 7, n1 = (k1.intValue() + d1) & 7; + int n0 = ((k0.intValue() >>> offset) + d0) & 7, n1 = ((k1.intValue() >>> offset) + d1) & 7; int u0 = n0 & 1; if (u0 != 0) @@ -140,15 +155,19 @@ public abstract class WNafUtil if ((d0 << 1) == 1 + u0) { - d0 = 1 - d0; + d0 ^= 1; } if ((d1 << 1) == 1 + u1) { - d1 = 1 - d1; + d1 ^= 1; } - k0 = k0.shiftRight(1); - k1 = k1.shiftRight(1); + if (++offset == 30) + { + offset = 0; + k0 = k0.shiftRight(30); + k1 = k1.shiftRight(30); + } jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF)); } @@ -164,19 +183,29 @@ public abstract class WNafUtil public static byte[] generateNaf(BigInteger k) { + if (k.signum() == 0) + { + return EMPTY_BYTES; + } + BigInteger _3k = k.shiftLeft(1).add(k); int digits = _3k.bitLength() - 1; byte[] naf = new byte[digits]; - for (int i = 1; i <= digits; ++i) - { - boolean _3kBit = _3k.testBit(i); - boolean kBit = k.testBit(i); + BigInteger diff = _3k.xor(k); - naf[i - 1] = (byte)(_3kBit == kBit ? 0 : kBit ? -1 : 1); + for (int i = 1; i < digits; ++i) + { + if (diff.testBit(i)) + { + naf[i - 1] = (byte)(k.testBit(i) ? -1 : 1); + ++i; + } } + naf[digits - 1] = 1; + return naf; } @@ -203,6 +232,10 @@ public abstract class WNafUtil { throw new IllegalArgumentException("'width' must be in the range [2, 8]"); } + if (k.signum() == 0) + { + return EMPTY_BYTES; + } byte[] wnaf = new byte[k.bitLength() + 1]; @@ -250,6 +283,24 @@ public abstract class WNafUtil return wnaf; } + public static int getNafWeight(BigInteger k) + { + if (k.signum() == 0) + { + return 0; + } + + BigInteger _3k = k.shiftLeft(1).add(k); + BigInteger diff = _3k.xor(k); + + return diff.bitCount(); + } + + public static WNafPreCompInfo getWNafPreCompInfo(ECPoint p) + { + return getWNafPreCompInfo(p.getCurve().getPreCompInfo(p, PRECOMP_NAME)); + } + public static WNafPreCompInfo getWNafPreCompInfo(PreCompInfo preCompInfo) { if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo)) @@ -291,10 +342,49 @@ public abstract class WNafUtil return w + 2; } + public static ECPoint mapPointWithPrecomp(ECPoint p, int width, boolean includeNegated, + ECPointMap pointMap) + { + ECCurve c = p.getCurve(); + WNafPreCompInfo wnafPreCompP = precompute(p, width, includeNegated); + + ECPoint q = pointMap.map(p); + WNafPreCompInfo wnafPreCompQ = getWNafPreCompInfo(c.getPreCompInfo(q, PRECOMP_NAME)); + + ECPoint twiceP = wnafPreCompP.getTwice(); + if (twiceP != null) + { + ECPoint twiceQ = pointMap.map(twiceP); + wnafPreCompQ.setTwice(twiceQ); + } + + ECPoint[] preCompP = wnafPreCompP.getPreComp(); + ECPoint[] preCompQ = new ECPoint[preCompP.length]; + for (int i = 0; i < preCompP.length; ++i) + { + preCompQ[i] = pointMap.map(preCompP[i]); + } + wnafPreCompQ.setPreComp(preCompQ); + + if (includeNegated) + { + ECPoint[] preCompNegQ = new ECPoint[preCompQ.length]; + for (int i = 0; i < preCompNegQ.length; ++i) + { + preCompNegQ[i] = preCompQ[i].negate(); + } + wnafPreCompQ.setPreCompNeg(preCompNegQ); + } + + c.setPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ); + + return q; + } + public static WNafPreCompInfo precompute(ECPoint p, int width, boolean includeNegated) { ECCurve c = p.getCurve(); - WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p)); + WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME)); ECPoint[] preComp = wnafPreCompInfo.getPreComp(); if (preComp == null) @@ -307,26 +397,28 @@ public abstract class WNafUtil if (preCompLen < reqPreCompLen) { - ECPoint twiceP = wnafPreCompInfo.getTwiceP(); - if (twiceP == null) - { - twiceP = preComp[0].twice().normalize(); - wnafPreCompInfo.setTwiceP(twiceP); - } - preComp = resizeTable(preComp, reqPreCompLen); - - /* - * TODO Okeya/Sakurai paper has precomputation trick and "Montgomery's Trick" to speed this up. - * Also, co-Z arithmetic could avoid the subsequent normalization too. - */ - for (int i = preCompLen; i < reqPreCompLen; i++) + if (reqPreCompLen == 2) { - /* - * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ..., - * 2^(width-1)-1 times p are computed - */ - preComp[i] = twiceP.add(preComp[i - 1]); + preComp[1] = preComp[0].threeTimes(); + } + else + { + ECPoint twiceP = wnafPreCompInfo.getTwice(); + if (twiceP == null) + { + twiceP = preComp[0].twice(); + wnafPreCompInfo.setTwice(twiceP); + } + + for (int i = preCompLen; i < reqPreCompLen; i++) + { + /* + * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ..., + * 2^(width-1)-1 times p are computed + */ + preComp[i] = twiceP.add(preComp[i - 1]); + } } /* @@ -365,7 +457,7 @@ public abstract class WNafUtil wnafPreCompInfo.setPreCompNeg(preCompNeg); } - c.setPreCompInfo(p, wnafPreCompInfo); + c.setPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo); return wnafPreCompInfo; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java index 351cfa19b..068c252f7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafMultiplier.java @@ -8,6 +8,9 @@ import java.math.BigInteger; */ public class WTauNafMultiplier extends AbstractECMultiplier { + // TODO Create WTauNafUtil class and move various functionality into it + static final String PRECOMP_NAME = "bc_wtnaf"; + /** * Multiplies a {@link org.spongycastle.math.ec.ECPoint.F2m ECPoint.F2m} * byk
using the reducedτ
-adic NAF (RTNAF) @@ -33,7 +36,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10); - return multiplyWTnaf(p, rho, curve.getPreCompInfo(p), a, mu); + return multiplyWTnaf(p, rho, curve.getPreCompInfo(p, PRECOMP_NAME), a, mu); } /** @@ -49,21 +52,12 @@ public class WTauNafMultiplier extends AbstractECMultiplier private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda, PreCompInfo preCompInfo, byte a, byte mu) { - ZTauElement[] alpha; - if (a == 0) - { - alpha = Tnaf.alpha0; - } - else - { - // a == 1 - alpha = Tnaf.alpha1; - } + ZTauElement[] alpha = (a == 0) ? Tnaf.alpha0 : Tnaf.alpha1; BigInteger tw = Tnaf.getTw(mu, Tnaf.WIDTH); byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH, - BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha); + BigInteger.valueOf(Tnaf.POW_2_WIDTH), tw, alpha); return multiplyFromWTnaf(p, u, preCompInfo); } @@ -77,8 +71,7 @@ public class WTauNafMultiplier extends AbstractECMultiplier * @param u The the WTNAF ofλ
.. * @returnλ * p
*/ - private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, - PreCompInfo preCompInfo) + private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo) { ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); byte a = curve.getA().toBigInteger().byteValue(); @@ -87,7 +80,10 @@ public class WTauNafMultiplier extends AbstractECMultiplier if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo)) { pu = Tnaf.getPreComp(p, a); - curve.setPreCompInfo(p, new WTauNafPreCompInfo(pu)); + + WTauNafPreCompInfo pre = new WTauNafPreCompInfo(); + pre.setPreComp(pu); + curve.setPreCompInfo(p, PRECOMP_NAME, pre); } else { @@ -99,16 +95,16 @@ public class WTauNafMultiplier extends AbstractECMultiplier for (int i = u.length - 1; i >= 0; i--) { q = Tnaf.tau(q); - if (u[i] != 0) + byte ui = u[i]; + if (ui != 0) { - if (u[i] > 0) + if (ui > 0) { - q = q.addSimple(pu[u[i]]); + q = q.addSimple(pu[ui]); } else { - // u[i] < 0 - q = q.subtractSimple(pu[-u[i]]); + q = q.subtractSimple(pu[-ui]); } } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java index 2373ff7a9..ed7d4ceb9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/WTauNafPreCompInfo.java @@ -4,7 +4,7 @@ package org.spongycastle.math.ec; * Class holding precomputation data for the WTNAF (Window *τ
-adic Non-Adjacent Form) algorithm. */ -class WTauNafPreCompInfo implements PreCompInfo +public class WTauNafPreCompInfo implements PreCompInfo { /** * Array holding the precomputedECPoint.F2m
s used for the @@ -12,28 +12,15 @@ class WTauNafPreCompInfo implements PreCompInfo * {@link org.spongycastle.math.ec.multiplier.WTauNafMultiplier.multiply() * WTauNafMultiplier.multiply()}. */ - private ECPoint.F2m[] preComp = null; + protected ECPoint.F2m[] preComp = null; - /** - * Constructor forWTauNafPreCompInfo
- * @param preComp Array holding the precomputedECPoint.F2m
s - * used for the WTNAF multiplication in- * {@link org.spongycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}
. - */ - WTauNafPreCompInfo(ECPoint.F2m[] preComp) - { - this.preComp = preComp; - } - - /** - * @return the array holding the precomputedECPoint.F2m
s - * used for the WTNAF multiplication in- * {@link org.spongycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}
. - */ - protected ECPoint.F2m[] getPreComp() + public ECPoint.F2m[] getPreComp() { return preComp; } + + public void setPreComp(ECPoint.F2m[] preComp) + { + this.preComp = preComp; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java new file mode 100644 index 000000000..c7d77397a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.djb; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat256; +import org.spongycastle.util.encoders.Hex; + +public class Curve25519 extends ECCurve.AbstractFp +{ + public static final BigInteger q = Nat256.toBigInteger(Curve25519Field.P); + + private static final int Curve25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED; + + protected Curve25519Point infinity; + + public Curve25519() + { + super(q); + + this.infinity = new Curve25519Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864"))); + this.order = new BigInteger(1, Hex.decode("1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED")); + this.cofactor = BigInteger.valueOf(8); + + this.coord = Curve25519_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new Curve25519(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN_MODIFIED: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new Curve25519FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new Curve25519Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new Curve25519Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java new file mode 100644 index 000000000..2fe484e1d --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Field.java @@ -0,0 +1,254 @@ +package org.spongycastle.math.ec.custom.djb; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat256; + +public class Curve25519Field +{ + private static final long M = 0xFFFFFFFFL; + + // 2^255 - 2^4 - 2^1 - 1 + static final int[] P = new int[]{ 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x7FFFFFFF }; + private static final int P7 = 0x7FFFFFFF; + private static final int[] PExt = new int[]{ 0x00000169, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x3FFFFFFF }; + private static final int PInv = 0x13; + + public static void add(int[] x, int[] y, int[] z) + { + Nat256.add(x, y, z); + if (Nat256.gte(z, P)) + { + subPFrom(z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + Nat.add(16, xx, yy, zz); + if (Nat.gte(16, zz, PExt)) + { + subPExtFrom(zz); + } + } + + public static void addOne(int[] x, int[] z) + { + Nat.inc(8, x, z); + if (Nat256.gte(z, P)) + { + subPFrom(z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat256.fromBigInteger(x); + while (Nat256.gte(z, P)) + { + Nat256.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(8, x, 0, z); + } + else + { + Nat256.add(x, P, z); + Nat.shiftDownBit(8, z, 0); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + Nat256.mulAddTo(x, y, zz); + if (Nat.gte(16, zz, PExt)) + { + subPExtFrom(zz); + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat256.isZero(x)) + { + Nat256.zero(z); + } + else + { + Nat256.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { +// assert xx[15] >>> 30 == 0; + + int xx07 = xx[7]; + Nat.shiftUpBit(8, xx, 8, xx07, z, 0); + int c = Nat256.mulByWordAddTo(PInv, xx, z) << 1; + int z7 = z[7]; + c += (z7 >>> 31) - (xx07 >>> 31); + z7 &= P7; + z7 += Nat.addWordTo(7, c * PInv, z); + z[7] = z7; + if (Nat256.gte(z, P)) + { + subPFrom(z); + } + } + + public static void reduce27(int x, int[] z) + { +// assert x >>> 26 == 0; + + int z7 = z[7]; + int c = (x << 1 | z7 >>> 31); + z7 &= P7; + z7 += Nat.addWordTo(7, c * PInv, z); + z[7] = z7; + if (Nat256.gte(z, P)) + { + subPFrom(z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat256.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat256.sub(x, y, z); + if (c != 0) + { + addPTo(z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(16, xx, yy, zz); + if (c != 0) + { + addPExtTo(zz); + } + } + + public static void twice(int[] x, int[] z) + { + Nat.shiftUpBit(8, x, 0, z); + if (Nat256.gte(z, P)) + { + subPFrom(z); + } + } + + private static int addPTo(int[] z) + { + long c = (z[0] & M) - PInv; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.decAt(7, z, 1); + } + c += (z[7] & M) + ((P7 + 1) & M); + z[7] = (int)c; + c >>= 32; + return (int)c; + } + + private static int addPExtTo(int[] zz) + { + long c = (zz[0] & M) + (PExt[0] & M); + zz[0] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.incAt(8, zz, 1); + } + c += (zz[8] & M) - PInv; + zz[8] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.decAt(15, zz, 9); + } + c += (zz[15] & M) + ((PExt[15] + 1) & M); + zz[15] = (int)c; + c >>= 32; + return (int)c; + } + + private static int subPFrom(int[] z) + { + long c = (z[0] & M) + PInv; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.incAt(7, z, 1); + } + c += (z[7] & M) - ((P7 + 1) & M); + z[7] = (int)c; + c >>= 32; + return (int)c; + } + + private static int subPExtFrom(int[] zz) + { + long c = (zz[0] & M) - (PExt[0] & M); + zz[0] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.decAt(8, zz, 1); + } + c += (zz[8] & M) + PInv; + zz[8] = (int)c; + c >>= 32; + if (c != 0) + { + c = Nat.incAt(15, zz, 9); + } + c += (zz[15] & M) - ((PExt[15] + 1) & M); + zz[15] = (int)c; + c >>= 32; + return (int)c; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java new file mode 100644 index 000000000..a5d5cb7be --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519FieldElement.java @@ -0,0 +1,234 @@ +package org.spongycastle.math.ec.custom.djb; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat256; +import org.spongycastle.util.Arrays; + +public class Curve25519FieldElement extends ECFieldElement +{ + public static final BigInteger Q = Curve25519.q; + + // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q) + private static final int[] PRECOMP_POW2 = new int[]{ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806, + 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480 }; + + protected int[] x; + + public Curve25519FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for Curve25519FieldElement"); + } + + this.x = Curve25519Field.fromBigInteger(x); + } + + public Curve25519FieldElement() + { + this.x = Nat256.create(); + } + + protected Curve25519FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat256.isZero(x); + } + + public boolean isOne() + { + return Nat256.isOne(x); + } + + public boolean testBitZero() + { + return Nat256.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat256.toBigInteger(x); + } + + public String getFieldName() + { + return "Curve25519Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat256.create(); + Curve25519Field.add(x, ((Curve25519FieldElement)b).x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat256.create(); + Curve25519Field.addOne(x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat256.create(); + Curve25519Field.subtract(x, ((Curve25519FieldElement)b).x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat256.create(); + Curve25519Field.multiply(x, ((Curve25519FieldElement)b).x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat256.create(); + Mod.invert(Curve25519Field.P, ((Curve25519FieldElement)b).x, z); + Curve25519Field.multiply(z, x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat256.create(); + Curve25519Field.negate(x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat256.create(); + Curve25519Field.square(x, z); + return new Curve25519FieldElement(z); + } + + public ECFieldElement invert() + { +// return new Curve25519FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat256.create(); + Mod.invert(Curve25519Field.P, x, z); + return new Curve25519FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + /* + * Q == 8m + 5, so we use Pocklington's method for this case. + * + * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1) + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 251 1s } { 1 0s } + * + * Therefore we need an addition chain containing 251 (the lengths of the repunits) + * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251] + */ + + int[] x1 = this.x; + if (Nat256.isZero(x1) || Nat256.isOne(x1)) + { + return this; + } + + int[] x2 = Nat256.create(); + Curve25519Field.square(x1, x2); + Curve25519Field.multiply(x2, x1, x2); + int[] x3 = x2; + Curve25519Field.square(x2, x3); + Curve25519Field.multiply(x3, x1, x3); + int[] x4 = Nat256.create(); + Curve25519Field.square(x3, x4); + Curve25519Field.multiply(x4, x1, x4); + int[] x7 = Nat256.create(); + Curve25519Field.squareN(x4, 3, x7); + Curve25519Field.multiply(x7, x3, x7); + int[] x11 = x3; + Curve25519Field.squareN(x7, 4, x11); + Curve25519Field.multiply(x11, x4, x11); + int[] x15 = x7; + Curve25519Field.squareN(x11, 4, x15); + Curve25519Field.multiply(x15, x4, x15); + int[] x30 = x4; + Curve25519Field.squareN(x15, 15, x30); + Curve25519Field.multiply(x30, x15, x30); + int[] x60 = x15; + Curve25519Field.squareN(x30, 30, x60); + Curve25519Field.multiply(x60, x30, x60); + int[] x120 = x30; + Curve25519Field.squareN(x60, 60, x120); + Curve25519Field.multiply(x120, x60, x120); + int[] x131 = x60; + Curve25519Field.squareN(x120, 11, x131); + Curve25519Field.multiply(x131, x11, x131); + int[] x251 = x11; + Curve25519Field.squareN(x131, 120, x251); + Curve25519Field.multiply(x251, x120, x251); + + int[] t1 = x251; + Curve25519Field.square(t1, t1); + + int[] t2 = x120; + Curve25519Field.square(t1, t2); + + if (Nat256.eq(x1, t2)) + { + return new Curve25519FieldElement(t1); + } + + /* + * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess, + * which is ((4x)^(m + 1))/2 mod Q + */ + Curve25519Field.multiply(t1, PRECOMP_POW2, t1); + + Curve25519Field.square(t1, t2); + + if (Nat256.eq(x1, t2)) + { + return new Curve25519FieldElement(t1); + } + + return null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof Curve25519FieldElement)) + { + return false; + } + + Curve25519FieldElement o = (Curve25519FieldElement)other; + return Nat256.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 8); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java new file mode 100644 index 000000000..a8b98a934 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/djb/Curve25519Point.java @@ -0,0 +1,348 @@ +package org.spongycastle.math.ec.custom.djb; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat256; + +public class Curve25519Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public Curve25519Point(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 + * + * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)} + */ + public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new Curve25519Point(null, getAffineXCoord(), getAffineYCoord()); + } + + public ECFieldElement getZCoord(int index) + { + if (index == 1) + { + return getJacobianModifiedW(); + } + + return super.getZCoord(index); + } + + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y, + Z1 = (Curve25519FieldElement)this.zs[0]; + Curve25519FieldElement X2 = (Curve25519FieldElement)b.getXCoord(), Y2 = (Curve25519FieldElement)b.getYCoord(), + Z2 = (Curve25519FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat256.createExt(); + int[] t2 = Nat256.create(); + int[] t3 = Nat256.create(); + int[] t4 = Nat256.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + Curve25519Field.square(Z1.x, S2); + + U2 = t2; + Curve25519Field.multiply(S2, X2.x, U2); + + Curve25519Field.multiply(S2, Z1.x, S2); + Curve25519Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + Curve25519Field.square(Z2.x, S1); + + U1 = tt1; + Curve25519Field.multiply(S1, X1.x, U1); + + Curve25519Field.multiply(S1, Z2.x, S1); + Curve25519Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat256.create(); + Curve25519Field.subtract(U1, U2, H); + + int[] R = t2; + Curve25519Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat256.isZero(H)) + { + if (Nat256.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = Nat256.create(); + Curve25519Field.square(H, HSquared); + + int[] G = Nat256.create(); + Curve25519Field.multiply(HSquared, H, G); + + int[] V = t3; + Curve25519Field.multiply(HSquared, U1, V); + + Curve25519Field.negate(G, G); + Nat256.mul(S1, G, tt1); + + c = Nat256.addBothTo(V, V, G); + Curve25519Field.reduce27(c, G); + + Curve25519FieldElement X3 = new Curve25519FieldElement(t4); + Curve25519Field.square(R, X3.x); + Curve25519Field.subtract(X3.x, G, X3.x); + + Curve25519FieldElement Y3 = new Curve25519FieldElement(G); + Curve25519Field.subtract(V, X3.x, Y3.x); + Curve25519Field.multiplyAddToExt(Y3.x, R, tt1); + Curve25519Field.reduce(tt1, Y3.x); + + Curve25519FieldElement Z3 = new Curve25519FieldElement(H); + if (!Z1IsOne) + { + Curve25519Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + Curve25519Field.multiply(Z3.x, Z2.x, Z3.x); + } + + int[] Z3Squared = (Z1IsOne && Z2IsOne) ? HSquared : null; + + // TODO If the result will only be used in a subsequent addition, we don't need W3 + Curve25519FieldElement W3 = calculateJacobianModifiedW((Curve25519FieldElement)Z3, Z3Squared); + + ECFieldElement[] zs = new ECFieldElement[]{ Z3, W3 }; + + return new Curve25519Point(curve, X3, Y3, zs, this.withCompression); + } + + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + return twiceJacobianModified(true); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twiceJacobianModified(false).add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity()) + { + return this; + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return this; + } + + return twiceJacobianModified(false).add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new Curve25519Point(this.getCurve(), this.x, this.y.negate(), this.zs, this.withCompression); + } + + protected Curve25519FieldElement calculateJacobianModifiedW(Curve25519FieldElement Z, int[] ZSquared) + { + Curve25519FieldElement a4 = (Curve25519FieldElement)this.getCurve().getA(); + if (Z.isOne()) + { + return a4; + } + + Curve25519FieldElement W = new Curve25519FieldElement(); + if (ZSquared == null) + { + ZSquared = W.x; + Curve25519Field.square(Z.x, ZSquared); + } + Curve25519Field.square(ZSquared, W.x); + Curve25519Field.multiply(W.x, a4.x, W.x); + return W; + } + + protected Curve25519FieldElement getJacobianModifiedW() + { + Curve25519FieldElement W = (Curve25519FieldElement)this.zs[1]; + if (W == null) + { + // NOTE: Rarely, twicePlus will result in the need for a lazy W1 calculation here + this.zs[1] = W = calculateJacobianModifiedW((Curve25519FieldElement)this.zs[0], null); + } + return W; + } + + protected Curve25519Point twiceJacobianModified(boolean calculateW) + { + Curve25519FieldElement X1 = (Curve25519FieldElement)this.x, Y1 = (Curve25519FieldElement)this.y, + Z1 = (Curve25519FieldElement)this.zs[0], W1 = getJacobianModifiedW(); + + int c; + + int[] M = Nat256.create(); + Curve25519Field.square(X1.x, M); + c = Nat256.addBothTo(M, M, M); + c += Nat256.addTo(W1.x, M); + Curve25519Field.reduce27(c, M); + + int[] _2Y1 = Nat256.create(); + Curve25519Field.twice(Y1.x, _2Y1); + + int[] _2Y1Squared = Nat256.create(); + Curve25519Field.multiply(_2Y1, Y1.x, _2Y1Squared); + + int[] S = Nat256.create(); + Curve25519Field.multiply(_2Y1Squared, X1.x, S); + Curve25519Field.twice(S, S); + + int[] _8T = Nat256.create(); + Curve25519Field.square(_2Y1Squared, _8T); + Curve25519Field.twice(_8T, _8T); + + Curve25519FieldElement X3 = new Curve25519FieldElement(_2Y1Squared); + Curve25519Field.square(M, X3.x); + Curve25519Field.subtract(X3.x, S, X3.x); + Curve25519Field.subtract(X3.x, S, X3.x); + + Curve25519FieldElement Y3 = new Curve25519FieldElement(S); + Curve25519Field.subtract(S, X3.x, Y3.x); + Curve25519Field.multiply(Y3.x, M, Y3.x); + Curve25519Field.subtract(Y3.x, _8T, Y3.x); + + Curve25519FieldElement Z3 = new Curve25519FieldElement(_2Y1); + if (!Nat256.isOne(Z1.x)) + { + Curve25519Field.multiply(Z3.x, Z1.x, Z3.x); + } + + Curve25519FieldElement W3 = null; + if (calculateW) + { + W3 = new Curve25519FieldElement(_8T); + Curve25519Field.multiply(W3.x, W1.x, W3.x); + Curve25519Field.twice(W3.x, W3.x); + } + + return new Curve25519Point(this.getCurve(), X3, Y3, new ECFieldElement[]{ Z3, W3 }, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java new file mode 100644 index 000000000..3c5d9cb31 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Curve.java @@ -0,0 +1,79 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP192K1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37")); + + private static final int SecP192K1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP192K1Point infinity; + + public SecP192K1Curve() + { + super(q); + + this.infinity = new SecP192K1Point(this, null, null); + + this.a = fromBigInteger(ECConstants.ZERO); + this.b = fromBigInteger(BigInteger.valueOf(3)); + this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP192K1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP192K1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP192K1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP192K1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP192K1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java new file mode 100644 index 000000000..b7e87f279 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Field.java @@ -0,0 +1,177 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat192; + +public class SecP192K1Field +{ + // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 + static final int[] P = new int[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0x00002391, 0x00000002 }; + private static final int P5 = 0xFFFFFFFF; + private static final int PExt11 = 0xFFFFFFFF; + private static final int PInv33 = 0x11C9; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat192.add(x, y, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + Nat.add33To(6, PInv33, z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(12, xx, yy, zz); + if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(12, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(6, x, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + Nat.add33To(6, PInv33, z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat192.fromBigInteger(x); + if (z[5] == P5 && Nat192.gte(z, P)) + { + Nat192.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(6, x, 0, z); + } + else + { + int c = Nat192.add(x, P, z); + Nat.shiftDownBit(6, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat192.createExt(); + Nat192.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat192.mulAddTo(x, y, zz); + if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(12, zz, PExtInv.length); + } + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat192.isZero(x)) + { + Nat192.zero(z); + } + else + { + Nat192.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long cc = Nat192.mul33Add(PInv33, xx, 6, xx, 0, z, 0); + int c = Nat192.mul33DWordAdd(PInv33, cc, z, 0); + + // assert c == 0L || c == 1L; + + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + Nat.add33To(6, PInv33, z); + } + } + + public static void reduce32(int x, int[] z) + { + if ((x != 0 && Nat192.mul33WordAdd(PInv33, x, z, 0) != 0) + || (z[5] == P5 && Nat192.gte(z, P))) + { + Nat.add33To(6, PInv33, z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat192.createExt(); + Nat192.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat192.createExt(); + Nat192.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat192.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat192.sub(x, y, z); + if (c != 0) + { + Nat.sub33From(6, PInv33, z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(12, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(12, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(6, x, 0, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + Nat.add33To(6, PInv33, z); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java new file mode 100644 index 000000000..449c560c1 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1FieldElement.java @@ -0,0 +1,213 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat192; +import org.spongycastle.util.Arrays; + +public class SecP192K1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP192K1Curve.q; + + protected int[] x; + + public SecP192K1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP192K1FieldElement"); + } + + this.x = SecP192K1Field.fromBigInteger(x); + } + + public SecP192K1FieldElement() + { + this.x = Nat192.create(); + } + + protected SecP192K1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat192.isZero(x); + } + + public boolean isOne() + { + return Nat192.isOne(x); + } + + public boolean testBitZero() + { + return Nat192.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat192.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP192K1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192K1Field.add(x, ((SecP192K1FieldElement)b).x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat192.create(); + SecP192K1Field.addOne(x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192K1Field.subtract(x, ((SecP192K1FieldElement)b).x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192K1Field.multiply(x, ((SecP192K1FieldElement)b).x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat192.create(); + Mod.invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z); + SecP192K1Field.multiply(z, x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat192.create(); + SecP192K1Field.negate(x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat192.create(); + SecP192K1Field.square(x, z); + return new SecP192K1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP192K1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat192.create(); + Mod.invert(SecP192K1Field.P, x, z); + return new SecP192K1FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + /* + * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1 + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s } + * + * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits) + * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159] + */ + + int[] x1 = this.x; + if (Nat192.isZero(x1) || Nat192.isOne(x1)) + { + return this; + } + + int[] x2 = Nat192.create(); + SecP192K1Field.square(x1, x2); + SecP192K1Field.multiply(x2, x1, x2); + int[] x3 = Nat192.create(); + SecP192K1Field.square(x2, x3); + SecP192K1Field.multiply(x3, x1, x3); + int[] x6 = Nat192.create(); + SecP192K1Field.squareN(x3, 3, x6); + SecP192K1Field.multiply(x6, x3, x6); + int[] x8 = x6; + SecP192K1Field.squareN(x6, 2, x8); + SecP192K1Field.multiply(x8, x2, x8); + int[] x16 = x2; + SecP192K1Field.squareN(x8, 8, x16); + SecP192K1Field.multiply(x16, x8, x16); + int[] x19 = x8; + SecP192K1Field.squareN(x16, 3, x19); + SecP192K1Field.multiply(x19, x3, x19); + int[] x35 = Nat192.create(); + SecP192K1Field.squareN(x19, 16, x35); + SecP192K1Field.multiply(x35, x16, x35); + int[] x70 = x16; + SecP192K1Field.squareN(x35, 35, x70); + SecP192K1Field.multiply(x70, x35, x70); + int[] x140 = x35; + SecP192K1Field.squareN(x70, 70, x140); + SecP192K1Field.multiply(x140, x70, x140); + int[] x159 = x70; + SecP192K1Field.squareN(x140, 19, x159); + SecP192K1Field.multiply(x159, x19, x159); + + int[] t1 = x159; + SecP192K1Field.squareN(t1, 20, t1); + SecP192K1Field.multiply(t1, x19, t1); + SecP192K1Field.squareN(t1, 4, t1); + SecP192K1Field.multiply(t1, x3, t1); + SecP192K1Field.squareN(t1, 6, t1); + SecP192K1Field.multiply(t1, x3, t1); + SecP192K1Field.square(t1, t1); + + int[] t2 = x3; + SecP192K1Field.square(t1, t2); + + return Nat192.eq(x1, t2) ? new SecP192K1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP192K1FieldElement)) + { + return false; + } + + SecP192K1FieldElement o = (SecP192K1FieldElement)other; + return Nat192.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 6); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java new file mode 100644 index 000000000..d2fc0ad29 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192K1Point.java @@ -0,0 +1,298 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat192; + +public class SecP192K1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP192K1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, + boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP192K1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + // B.3 pg 62 + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Y1 = (SecP192K1FieldElement)this.y; + SecP192K1FieldElement X2 = (SecP192K1FieldElement)b.getXCoord(), Y2 = (SecP192K1FieldElement)b.getYCoord(); + + SecP192K1FieldElement Z1 = (SecP192K1FieldElement)this.zs[0]; + SecP192K1FieldElement Z2 = (SecP192K1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat192.createExt(); + int[] t2 = Nat192.create(); + int[] t3 = Nat192.create(); + int[] t4 = Nat192.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP192K1Field.square(Z1.x, S2); + + U2 = t2; + SecP192K1Field.multiply(S2, X2.x, U2); + + SecP192K1Field.multiply(S2, Z1.x, S2); + SecP192K1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP192K1Field.square(Z2.x, S1); + + U1 = tt1; + SecP192K1Field.multiply(S1, X1.x, U1); + + SecP192K1Field.multiply(S1, Z2.x, S1); + SecP192K1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat192.create(); + SecP192K1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP192K1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat192.isZero(H)) + { + if (Nat192.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP192K1Field.square(H, HSquared); + + int[] G = Nat192.create(); + SecP192K1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP192K1Field.multiply(HSquared, U1, V); + + SecP192K1Field.negate(G, G); + Nat192.mul(S1, G, tt1); + + c = Nat192.addBothTo(V, V, G); + SecP192K1Field.reduce32(c, G); + + SecP192K1FieldElement X3 = new SecP192K1FieldElement(t4); + SecP192K1Field.square(R, X3.x); + SecP192K1Field.subtract(X3.x, G, X3.x); + + SecP192K1FieldElement Y3 = new SecP192K1FieldElement(G); + SecP192K1Field.subtract(V, X3.x, Y3.x); + SecP192K1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP192K1Field.reduce(tt1, Y3.x); + + SecP192K1FieldElement Z3 = new SecP192K1FieldElement(H); + if (!Z1IsOne) + { + SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP192K1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[] { Z3 }; + + return new SecP192K1Point(curve, X3, Y3, zs, this.withCompression); + } + + // B.3 pg 62 + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP192K1FieldElement Y1 = (SecP192K1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.x, Z1 = (SecP192K1FieldElement)this.zs[0]; + + int c; + + int[] Y1Squared = Nat192.create(); + SecP192K1Field.square(Y1.x, Y1Squared); + + int[] T = Nat192.create(); + SecP192K1Field.square(Y1Squared, T); + + int[] M = Nat192.create(); + SecP192K1Field.square(X1.x, M); + c = Nat192.addBothTo(M, M, M); + SecP192K1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP192K1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(6, S, 2, 0); + SecP192K1Field.reduce32(c, S); + + int[] t1 = Nat192.create(); + c = Nat.shiftUpBits(6, T, 3, 0, t1); + SecP192K1Field.reduce32(c, t1); + + SecP192K1FieldElement X3 = new SecP192K1FieldElement(T); + SecP192K1Field.square(M, X3.x); + SecP192K1Field.subtract(X3.x, S, X3.x); + SecP192K1Field.subtract(X3.x, S, X3.x); + + SecP192K1FieldElement Y3 = new SecP192K1FieldElement(S); + SecP192K1Field.subtract(S, X3.x, Y3.x); + SecP192K1Field.multiply(Y3.x, M, Y3.x); + SecP192K1Field.subtract(Y3.x, t1, Y3.x); + + SecP192K1FieldElement Z3 = new SecP192K1FieldElement(M); + SecP192K1Field.twice(Y1.x, Z3.x); + if (!Z1.isOne()) + { + SecP192K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP192K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP192K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java new file mode 100644 index 000000000..705069fca --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Curve.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP192R1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")); + + private static final int SecP192R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP192R1Point infinity; + + public SecP192R1Curve() + { + super(q); + + this.infinity = new SecP192R1Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"))); + this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP192R1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP192R1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP192R1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP192R1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP192R1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java new file mode 100644 index 000000000..4188b8f81 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Field.java @@ -0,0 +1,286 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat192; + +public class SecP192R1Field +{ + private static final long M = 0xFFFFFFFFL; + + // 2^192 - 2^64 - 1 + static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001, + 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFE, + 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000002 }; + private static final int P5 = 0xFFFFFFFF; + private static final int PExt11 = 0xFFFFFFFF; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat192.add(x, y, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(12, xx, yy, zz); + if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(12, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(6, x, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + addPInvTo(z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat192.fromBigInteger(x); + if (z[5] == P5 && Nat192.gte(z, P)) + { + Nat192.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(6, x, 0, z); + } + else + { + int c = Nat192.add(x, P, z); + Nat.shiftDownBit(6, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat192.createExt(); + Nat192.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat192.mulAddTo(x, y, zz); + if (c != 0 || (zz[11] == PExt11 && Nat.gte(12, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(12, zz, PExtInv.length); + } + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat192.isZero(x)) + { + Nat192.zero(z); + } + else + { + Nat192.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long xx06 = xx[6] & M, xx07 = xx[7] & M, xx08 = xx[8] & M; + long xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M; + + long t0 = xx06 + xx10; + long t1 = xx07 + xx11; + + long cc = 0; + cc += (xx[0] & M) + t0; + int z0 = (int)cc; + cc >>= 32; + cc += (xx[1] & M) + t1; + z[1] = (int)cc; + cc >>= 32; + + t0 += xx08; + t1 += xx09; + + cc += (xx[2] & M) + t0; + long z2 = cc & M; + cc >>= 32; + cc += (xx[3] & M) + t1; + z[3] = (int)cc; + cc >>= 32; + + t0 -= xx06; + t1 -= xx07; + + cc += (xx[4] & M) + t0; + z[4] = (int)cc; + cc >>= 32; + cc += (xx[5] & M) + t1; + z[5] = (int)cc; + cc >>= 32; + + z2 += cc; + + cc += (z0 & M); + z[0] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[1] & M); + z[1] = (int)cc; + z2 += cc >> 32; + } + z[2] = (int)z2; + cc = z2 >> 32; + +// assert cc == 0 || cc == 1; + + if ((cc != 0 && Nat.incAt(6, z, 3) != 0) + || (z[5] == P5 && Nat192.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void reduce32(int x, int[] z) + { + long cc = 0; + + if (x != 0) + { + long xx06 = x & M; + + cc += (z[0] & M) + xx06; + z[0] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[1] & M); + z[1] = (int)cc; + cc >>= 32; + } + cc += (z[2] & M) + xx06; + z[2] = (int)cc; + cc >>= 32; + +// assert cc == 0 || cc == 1; + } + + if ((cc != 0 && Nat.incAt(6, z, 3) != 0) + || (z[5] == P5 && Nat192.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat192.createExt(); + Nat192.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat192.createExt(); + Nat192.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat192.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat192.sub(x, y, z); + if (c != 0) + { + subPInvFrom(z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(12, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(12, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(6, x, 0, z); + if (c != 0 || (z[5] == P5 && Nat192.gte(z, P))) + { + addPInvTo(z); + } + } + + private static void addPInvTo(int[] z) + { + long c = (z[0] & M) + 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + } + c += (z[2] & M) + 1; + z[2] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.incAt(6, z, 3); + } + } + + private static void subPInvFrom(int[] z) + { + long c = (z[0] & M) - 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + } + c += (z[2] & M) - 1; + z[2] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.decAt(6, z, 3); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java new file mode 100644 index 000000000..2ab5030c1 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1FieldElement.java @@ -0,0 +1,190 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat192; +import org.spongycastle.util.Arrays; + +public class SecP192R1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP192R1Curve.q; + + protected int[] x; + + public SecP192R1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP192R1FieldElement"); + } + + this.x = SecP192R1Field.fromBigInteger(x); + } + + public SecP192R1FieldElement() + { + this.x = Nat192.create(); + } + + protected SecP192R1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat192.isZero(x); + } + + public boolean isOne() + { + return Nat192.isOne(x); + } + + public boolean testBitZero() + { + return Nat192.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat192.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP192R1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192R1Field.add(x, ((SecP192R1FieldElement)b).x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat192.create(); + SecP192R1Field.addOne(x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192R1Field.subtract(x, ((SecP192R1FieldElement)b).x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat192.create(); + SecP192R1Field.multiply(x, ((SecP192R1FieldElement)b).x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat192.create(); + Mod.invert(SecP192R1Field.P, ((SecP192R1FieldElement)b).x, z); + SecP192R1Field.multiply(z, x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat192.create(); + SecP192R1Field.negate(x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat192.create(); + SecP192R1Field.square(x, z); + return new SecP192R1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP192R1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat192.create(); + Mod.invert(SecP192R1Field.P, x, z); + return new SecP192R1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + // Raise this element to the exponent 2^190 - 2^62 + + int[] x1 = this.x; + if (Nat192.isZero(x1) || Nat192.isOne(x1)) + { + return this; + } + + int[] t1 = Nat192.create(); + int[] t2 = Nat192.create(); + + SecP192R1Field.square(x1, t1); + SecP192R1Field.multiply(t1, x1, t1); + + SecP192R1Field.squareN(t1, 2, t2); + SecP192R1Field.multiply(t2, t1, t2); + + SecP192R1Field.squareN(t2, 4, t1); + SecP192R1Field.multiply(t1, t2, t1); + + SecP192R1Field.squareN(t1, 8, t2); + SecP192R1Field.multiply(t2, t1, t2); + + SecP192R1Field.squareN(t2, 16, t1); + SecP192R1Field.multiply(t1, t2, t1); + + SecP192R1Field.squareN(t1, 32, t2); + SecP192R1Field.multiply(t2, t1, t2); + + SecP192R1Field.squareN(t2, 64, t1); + SecP192R1Field.multiply(t1, t2, t1); + + SecP192R1Field.squareN(t1, 62, t1); + SecP192R1Field.square(t1, t2); + + return Nat192.eq(x1, t2) ? new SecP192R1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP192R1FieldElement)) + { + return false; + } + + SecP192R1FieldElement o = (SecP192R1FieldElement)other; + return Nat192.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 6); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java new file mode 100644 index 000000000..9d611267d --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP192R1Point.java @@ -0,0 +1,310 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat192; + +public class SecP192R1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP192R1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP192R1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + // B.3 pg 62 + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Y1 = (SecP192R1FieldElement)this.y; + SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.getXCoord(), Y2 = (SecP192R1FieldElement)b.getYCoord(); + + SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.zs[0]; + SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat192.createExt(); + int[] t2 = Nat192.create(); + int[] t3 = Nat192.create(); + int[] t4 = Nat192.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP192R1Field.square(Z1.x, S2); + + U2 = t2; + SecP192R1Field.multiply(S2, X2.x, U2); + + SecP192R1Field.multiply(S2, Z1.x, S2); + SecP192R1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP192R1Field.square(Z2.x, S1); + + U1 = tt1; + SecP192R1Field.multiply(S1, X1.x, U1); + + SecP192R1Field.multiply(S1, Z2.x, S1); + SecP192R1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat192.create(); + SecP192R1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP192R1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat192.isZero(H)) + { + if (Nat192.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP192R1Field.square(H, HSquared); + + int[] G = Nat192.create(); + SecP192R1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP192R1Field.multiply(HSquared, U1, V); + + SecP192R1Field.negate(G, G); + Nat192.mul(S1, G, tt1); + + c = Nat192.addBothTo(V, V, G); + SecP192R1Field.reduce32(c, G); + + SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4); + SecP192R1Field.square(R, X3.x); + SecP192R1Field.subtract(X3.x, G, X3.x); + + SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G); + SecP192R1Field.subtract(V, X3.x, Y3.x); + SecP192R1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP192R1Field.reduce(tt1, Y3.x); + + SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H); + if (!Z1IsOne) + { + SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP192R1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP192R1Point(curve, X3, Y3, zs, this.withCompression); + } + + // B.3 pg 62 + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.x, Z1 = (SecP192R1FieldElement)this.zs[0]; + + int c; + int[] t1 = Nat192.create(); + int[] t2 = Nat192.create(); + + int[] Y1Squared = Nat192.create(); + SecP192R1Field.square(Y1.x, Y1Squared); + + int[] T = Nat192.create(); + SecP192R1Field.square(Y1Squared, T); + + boolean Z1IsOne = Z1.isOne(); + + int[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP192R1Field.square(Z1.x, Z1Squared); + } + + SecP192R1Field.subtract(X1.x, Z1Squared, t1); + + int[] M = t2; + SecP192R1Field.add(X1.x, Z1Squared, M); + SecP192R1Field.multiply(M, t1, M); + c = Nat192.addBothTo(M, M, M); + SecP192R1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP192R1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(6, S, 2, 0); + SecP192R1Field.reduce32(c, S); + + c = Nat.shiftUpBits(6, T, 3, 0, t1); + SecP192R1Field.reduce32(c, t1); + + SecP192R1FieldElement X3 = new SecP192R1FieldElement(T); + SecP192R1Field.square(M, X3.x); + SecP192R1Field.subtract(X3.x, S, X3.x); + SecP192R1Field.subtract(X3.x, S, X3.x); + + SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S); + SecP192R1Field.subtract(S, X3.x, Y3.x); + SecP192R1Field.multiply(Y3.x, M, Y3.x); + SecP192R1Field.subtract(Y3.x, t1, Y3.x); + + SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M); + SecP192R1Field.twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP192R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP192R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java new file mode 100644 index 000000000..9b26b6f8d --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Curve.java @@ -0,0 +1,78 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP224K1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D")); + + private static final int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP224K1Point infinity; + + public SecP224K1Curve() + { + super(q); + + this.infinity = new SecP224K1Point(this, null, null); + + this.a = fromBigInteger(ECConstants.ZERO); + this.b = fromBigInteger(BigInteger.valueOf(5)); + this.order = new BigInteger(1, Hex.decode("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7")); + this.cofactor = BigInteger.valueOf(1); + this.coord = SECP224K1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP224K1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP224K1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP224K1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP224K1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java new file mode 100644 index 000000000..0db90e56c --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Field.java @@ -0,0 +1,178 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat224; + +public class SecP224K1Field +{ + // 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1 + static final int[] P = new int[]{ 0xFFFFE56D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x02C23069, 0x00003526, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFCADA, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFD3DCF97, 0xFFFFCAD9, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00003525, 0x00000002 }; + private static final int P6 = 0xFFFFFFFF; + private static final int PExt13 = 0xFFFFFFFF; + private static final int PInv33 = 0x1A93; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat224.add(x, y, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + Nat.add33To(7, PInv33, z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(14, xx, yy, zz); + if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(14, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(7, x, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + Nat.add33To(7, PInv33, z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat224.fromBigInteger(x); + if (z[6] == P6 && Nat224.gte(z, P)) + { + Nat.add33To(7, PInv33, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(7, x, 0, z); + } + else + { + int c = Nat224.add(x, P, z); + Nat.shiftDownBit(7, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat224.createExt(); + Nat224.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat224.mulAddTo(x, y, zz); + if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(14, zz, PExtInv.length); + } + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat224.isZero(x)) + { + Nat224.zero(z); + } + else + { + Nat224.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long cc = Nat224.mul33Add(PInv33, xx, 7, xx, 0, z, 0); + int c = Nat224.mul33DWordAdd(PInv33, cc, z, 0); + + // assert c == 0L || c == 1L; + + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + Nat.add33To(7, PInv33, z); + } + } + + public static void reduce32(int x, int[] z) + { + if ((x != 0 && Nat224.mul33WordAdd(PInv33, x, z, 0) != 0) + || (z[6] == P6 && Nat224.gte(z, P))) + { + Nat.add33To(7, PInv33, z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat224.createExt(); + Nat224.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat224.createExt(); + Nat224.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat224.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat224.sub(x, y, z); + if (c != 0) + { + Nat.sub33From(7, PInv33, z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(14, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(14, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(7, x, 0, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + Nat.add33To(7, PInv33, z); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java new file mode 100644 index 000000000..655b9592a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1FieldElement.java @@ -0,0 +1,243 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat224; +import org.spongycastle.util.Arrays; + +public class SecP224K1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP224K1Curve.q; + + // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q) + private static final int[] PRECOMP_POW2 = new int[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8, + 0xa85558fc, 0x1eaef5d7, 0x8edf154c }; + + protected int[] x; + + public SecP224K1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP224K1FieldElement"); + } + + this.x = SecP224K1Field.fromBigInteger(x); + } + + public SecP224K1FieldElement() + { + this.x = Nat224.create(); + } + + protected SecP224K1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat224.isZero(x); + } + + public boolean isOne() + { + return Nat224.isOne(x); + } + + public boolean testBitZero() + { + return Nat224.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat224.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP224K1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224K1Field.add(x, ((SecP224K1FieldElement)b).x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat224.create(); + SecP224K1Field.addOne(x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224K1Field.subtract(x, ((SecP224K1FieldElement)b).x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224K1Field.multiply(x, ((SecP224K1FieldElement)b).x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat224.create(); + Mod.invert(SecP224K1Field.P, ((SecP224K1FieldElement)b).x, z); + SecP224K1Field.multiply(z, x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat224.create(); + SecP224K1Field.negate(x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat224.create(); + SecP224K1Field.square(x, z); + return new SecP224K1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP224K1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat224.create(); + Mod.invert(SecP224K1Field.P, x, z); + return new SecP224K1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + /* + * Q == 8m + 5, so we use Pocklington's method for this case. + * + * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1) + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s} + * + * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits) + * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191] + */ + + int[] x1 = this.x; + if (Nat224.isZero(x1) || Nat224.isOne(x1)) + { + return this; + } + + int[] x2 = Nat224.create(); + SecP224K1Field.square(x1, x2); + SecP224K1Field.multiply(x2, x1, x2); + int[] x3 = x2; + SecP224K1Field.square(x2, x3); + SecP224K1Field.multiply(x3, x1, x3); + int[] x4 = Nat224.create(); + SecP224K1Field.square(x3, x4); + SecP224K1Field.multiply(x4, x1, x4); + int[] x8 = Nat224.create(); + SecP224K1Field.squareN(x4, 4, x8); + SecP224K1Field.multiply(x8, x4, x8); + int[] x11 = Nat224.create(); + SecP224K1Field.squareN(x8, 3, x11); + SecP224K1Field.multiply(x11, x3, x11); + int[] x19 = x11; + SecP224K1Field.squareN(x11, 8, x19); + SecP224K1Field.multiply(x19, x8, x19); + int[] x23 = x8; + SecP224K1Field.squareN(x19, 4, x23); + SecP224K1Field.multiply(x23, x4, x23); + int[] x42 = x4; + SecP224K1Field.squareN(x23, 19, x42); + SecP224K1Field.multiply(x42, x19, x42); + int[] x84 = Nat224.create(); + SecP224K1Field.squareN(x42, 42, x84); + SecP224K1Field.multiply(x84, x42, x84); + int[] x107 = x42; + SecP224K1Field.squareN(x84, 23, x107); + SecP224K1Field.multiply(x107, x23, x107); + int[] x191 = x23; + SecP224K1Field.squareN(x107, 84, x191); + SecP224K1Field.multiply(x191, x84, x191); + + int[] t1 = x191; + SecP224K1Field.squareN(t1, 20, t1); + SecP224K1Field.multiply(t1, x19, t1); + SecP224K1Field.squareN(t1, 3, t1); + SecP224K1Field.multiply(t1, x1, t1); + SecP224K1Field.squareN(t1, 2, t1); + SecP224K1Field.multiply(t1, x1, t1); + SecP224K1Field.squareN(t1, 4, t1); + SecP224K1Field.multiply(t1, x3, t1); + SecP224K1Field.square(t1, t1); + + int[] t2 = x84; + SecP224K1Field.square(t1, t2); + + if (Nat224.eq(x1, t2)) + { + return new SecP224K1FieldElement(t1); + } + + /* + * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess, + * which is ((4x)^(m + 1))/2 mod Q + */ + SecP224K1Field.multiply(t1, PRECOMP_POW2, t1); + + SecP224K1Field.square(t1, t2); + + if (Nat224.eq(x1, t2)) + { + return new SecP224K1FieldElement(t1); + } + + return null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP224K1FieldElement)) + { + return false; + } + + SecP224K1FieldElement o = (SecP224K1FieldElement)other; + return Nat224.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 7); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java new file mode 100644 index 000000000..e33bc5fd5 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224K1Point.java @@ -0,0 +1,298 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat224; + +public class SecP224K1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP224K1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, + boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP224K1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + // B.3 pg 62 + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Y1 = (SecP224K1FieldElement)this.y; + SecP224K1FieldElement X2 = (SecP224K1FieldElement)b.getXCoord(), Y2 = (SecP224K1FieldElement)b.getYCoord(); + + SecP224K1FieldElement Z1 = (SecP224K1FieldElement)this.zs[0]; + SecP224K1FieldElement Z2 = (SecP224K1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat224.createExt(); + int[] t2 = Nat224.create(); + int[] t3 = Nat224.create(); + int[] t4 = Nat224.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP224K1Field.square(Z1.x, S2); + + U2 = t2; + SecP224K1Field.multiply(S2, X2.x, U2); + + SecP224K1Field.multiply(S2, Z1.x, S2); + SecP224K1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP224K1Field.square(Z2.x, S1); + + U1 = tt1; + SecP224K1Field.multiply(S1, X1.x, U1); + + SecP224K1Field.multiply(S1, Z2.x, S1); + SecP224K1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat224.create(); + SecP224K1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP224K1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat224.isZero(H)) + { + if (Nat224.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP224K1Field.square(H, HSquared); + + int[] G = Nat224.create(); + SecP224K1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP224K1Field.multiply(HSquared, U1, V); + + SecP224K1Field.negate(G, G); + Nat224.mul(S1, G, tt1); + + c = Nat224.addBothTo(V, V, G); + SecP224K1Field.reduce32(c, G); + + SecP224K1FieldElement X3 = new SecP224K1FieldElement(t4); + SecP224K1Field.square(R, X3.x); + SecP224K1Field.subtract(X3.x, G, X3.x); + + SecP224K1FieldElement Y3 = new SecP224K1FieldElement(G); + SecP224K1Field.subtract(V, X3.x, Y3.x); + SecP224K1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP224K1Field.reduce(tt1, Y3.x); + + SecP224K1FieldElement Z3 = new SecP224K1FieldElement(H); + if (!Z1IsOne) + { + SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP224K1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[] { Z3 }; + + return new SecP224K1Point(curve, X3, Y3, zs, this.withCompression); + } + + // B.3 pg 62 + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP224K1FieldElement Y1 = (SecP224K1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.x, Z1 = (SecP224K1FieldElement)this.zs[0]; + + int c; + + int[] Y1Squared = Nat224.create(); + SecP224K1Field.square(Y1.x, Y1Squared); + + int[] T = Nat224.create(); + SecP224K1Field.square(Y1Squared, T); + + int[] M = Nat224.create(); + SecP224K1Field.square(X1.x, M); + c = Nat224.addBothTo(M, M, M); + SecP224K1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP224K1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(7, S, 2, 0); + SecP224K1Field.reduce32(c, S); + + int[] t1 = Nat224.create(); + c = Nat.shiftUpBits(7, T, 3, 0, t1); + SecP224K1Field.reduce32(c, t1); + + SecP224K1FieldElement X3 = new SecP224K1FieldElement(T); + SecP224K1Field.square(M, X3.x); + SecP224K1Field.subtract(X3.x, S, X3.x); + SecP224K1Field.subtract(X3.x, S, X3.x); + + SecP224K1FieldElement Y3 = new SecP224K1FieldElement(S); + SecP224K1Field.subtract(S, X3.x, Y3.x); + SecP224K1Field.multiply(Y3.x, M, Y3.x); + SecP224K1Field.subtract(Y3.x, t1, Y3.x); + + SecP224K1FieldElement Z3 = new SecP224K1FieldElement(M); + SecP224K1Field.twice(Y1.x, Z3.x); + if (!Z1.isOne()) + { + SecP224K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP224K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP224K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java new file mode 100644 index 000000000..e81cca7ff --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Curve.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP224R1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")); + + private static final int SecP224R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP224R1Point infinity; + + public SecP224R1Curve() + { + super(q); + + this.infinity = new SecP224R1Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"))); + this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP224R1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP224R1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP224R1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP224R1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP224R1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java new file mode 100644 index 000000000..1722e158a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Field.java @@ -0,0 +1,298 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat224; + +public class SecP224R1Field +{ + private static final long M = 0xFFFFFFFFL; + + // 2^224 - 2^96 + 1 + static final int[] P = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 }; + private static final int P6 = 0xFFFFFFFF; + private static final int PExt13 = 0xFFFFFFFF; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat224.add(x, y, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(14, xx, yy, zz); + if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(14, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(7, x, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + addPInvTo(z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat224.fromBigInteger(x); + if (z[6] == P6 && Nat224.gte(z, P)) + { + Nat224.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(7, x, 0, z); + } + else + { + int c = Nat224.add(x, P, z); + Nat.shiftDownBit(7, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat224.createExt(); + Nat224.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat224.mulAddTo(x, y, zz); + if (c != 0 || (zz[13] == PExt13 && Nat.gte(14, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(14, zz, PExtInv.length); + } + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat224.isZero(x)) + { + Nat224.zero(z); + } + else + { + Nat224.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long xx10 = xx[10] & M, xx11 = xx[11] & M, xx12 = xx[12] & M, xx13 = xx[13] & M; + + final long n = 1; + + long t0 = (xx[7] & M) + xx11 - n; + long t1 = (xx[8] & M) + xx12; + long t2 = (xx[9] & M) + xx13; + + long cc = 0; + cc += (xx[0] & M) - t0; + long z0 = cc & M; + cc >>= 32; + cc += (xx[1] & M) - t1; + z[1] = (int)cc; + cc >>= 32; + cc += (xx[2] & M) - t2; + z[2] = (int)cc; + cc >>= 32; + cc += (xx[3] & M) + t0 - xx10; + long z3 = cc & M; + cc >>= 32; + cc += (xx[4] & M) + t1 - xx11; + z[4] = (int)cc; + cc >>= 32; + cc += (xx[5] & M) + t2 - xx12; + z[5] = (int)cc; + cc >>= 32; + cc += (xx[6] & M) + xx10 - xx13; + z[6] = (int)cc; + cc >>= 32; + cc += n; + +// assert cc >= 0; + + z3 += cc; + + z0 -= cc; + z[0] = (int)z0; + cc = z0 >> 32; + if (cc != 0) + { + cc += (z[1] & M); + z[1] = (int)cc; + cc >>= 32; + cc += (z[2] & M); + z[2] = (int)cc; + z3 += cc >> 32; + } + z[3] = (int)z3; + cc = z3 >> 32; + +// assert cc == 0 || cc == 1; + + if ((cc != 0 && Nat.incAt(7, z, 4) != 0) + || (z[6] == P6 && Nat224.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void reduce32(int x, int[] z) + { + long cc = 0; + + if (x != 0) + { + long xx07 = x & M; + + cc += (z[0] & M) - xx07; + z[0] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[1] & M); + z[1] = (int)cc; + cc >>= 32; + cc += (z[2] & M); + z[2] = (int)cc; + cc >>= 32; + } + cc += (z[3] & M) + xx07; + z[3] = (int)cc; + cc >>= 32; + +// assert cc == 0 || cc == 1; + } + + if ((cc != 0 && Nat.incAt(7, z, 4) != 0) + || (z[6] == P6 && Nat224.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat224.createExt(); + Nat224.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat224.createExt(); + Nat224.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat224.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat224.sub(x, y, z); + if (c != 0) + { + subPInvFrom(z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(14, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(14, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(7, x, 0, z); + if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) + { + addPInvTo(z); + } + } + + private static void addPInvTo(int[] z) + { + long c = (z[0] & M) - 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) + 1; + z[3] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.incAt(7, z, 4); + } + } + + private static void subPInvFrom(int[] z) + { + long c = (z[0] & M) + 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) - 1; + z[3] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.decAt(7, z, 4); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java new file mode 100644 index 000000000..3a82fcab3 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1FieldElement.java @@ -0,0 +1,273 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat224; +import org.spongycastle.util.Arrays; + +public class SecP224R1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP224R1Curve.q; + + protected int[] x; + + public SecP224R1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP224R1FieldElement"); + } + + this.x = SecP224R1Field.fromBigInteger(x); + } + + public SecP224R1FieldElement() + { + this.x = Nat224.create(); + } + + protected SecP224R1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat224.isZero(x); + } + + public boolean isOne() + { + return Nat224.isOne(x); + } + + public boolean testBitZero() + { + return Nat224.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat224.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP224R1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224R1Field.add(x, ((SecP224R1FieldElement)b).x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat224.create(); + SecP224R1Field.addOne(x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224R1Field.subtract(x, ((SecP224R1FieldElement)b).x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat224.create(); + SecP224R1Field.multiply(x, ((SecP224R1FieldElement)b).x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat224.create(); + Mod.invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z); + SecP224R1Field.multiply(z, x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat224.create(); + SecP224R1Field.negate(x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat224.create(); + SecP224R1Field.square(x, z); + return new SecP224R1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP224R1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat224.create(); + Mod.invert(SecP224R1Field.P, x, z); + return new SecP224R1FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + int[] c = this.x; + if (Nat224.isZero(c) || Nat224.isOne(c)) + { + return this; + } + + int[] nc = Nat224.create(); + SecP224R1Field.negate(c, nc); + + int[] r = Mod.random(SecP224R1Field.P); + int[] t = Nat224.create(); + + if (!isSquare(c)) + { + return null; + } + + while (!trySqrt(nc, r, t)) + { + SecP224R1Field.addOne(r, r); + } + + SecP224R1Field.square(t, r); + + return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP224R1FieldElement)) + { + return false; + } + + SecP224R1FieldElement o = (SecP224R1FieldElement)other; + return Nat224.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 7); + } + + private static boolean isSquare(int[] x) + { + int[] t1 = Nat224.create(); + int[] t2 = Nat224.create(); + Nat224.copy(x, t1); + + for (int i = 0; i < 7; ++i) + { + Nat224.copy(t1, t2); + SecP224R1Field.squareN(t1, 1 << i, t1); + SecP224R1Field.multiply(t1, t2, t1); + } + + SecP224R1Field.squareN(t1, 95, t1); + return Nat224.isOne(t1); + } + + private static void RM(int[] nc, int[] d0, int[] e0, int[] d1, int[] e1, int[] f1, int[] t) + { + SecP224R1Field.multiply(e1, e0, t); + SecP224R1Field.multiply(t, nc, t); + SecP224R1Field.multiply(d1, d0, f1); + SecP224R1Field.add(f1, t, f1); + SecP224R1Field.multiply(d1, e0, t); + Nat224.copy(f1, d1); + SecP224R1Field.multiply(e1, d0, e1); + SecP224R1Field.add(e1, t, e1); + SecP224R1Field.square(e1, f1); + SecP224R1Field.multiply(f1, nc, f1); + } + + private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t) + { + Nat224.copy(nc, f1); + + int[] d0 = Nat224.create(); + int[] e0 = Nat224.create(); + + for (int i = 0; i < 7; ++i) + { + Nat224.copy(d1, d0); + Nat224.copy(e1, e0); + + int j = 1 << i; + while (--j >= 0) + { + RS(d1, e1, f1, t); + } + + RM(nc, d0, e0, d1, e1, f1, t); + } + } + + private static void RS(int[] d, int[] e, int[] f, int[] t) + { + SecP224R1Field.multiply(e, d, e); + SecP224R1Field.twice(e, e); + SecP224R1Field.square(d, t); + SecP224R1Field.add(f, t, d); + SecP224R1Field.multiply(f, t, f); + int c = Nat.shiftUpBits(7, f, 2, 0); + SecP224R1Field.reduce32(c, f); + } + + private static boolean trySqrt(int[] nc, int[] r, int[] t) + { + int[] d1 = Nat224.create(); + Nat224.copy(r, d1); + int[] e1 = Nat224.create(); + e1[0] = 1; + int[] f1 = Nat224.create(); + RP(nc, d1, e1, f1, t); + + int[] d0 = Nat224.create(); + int[] e0 = Nat224.create(); + + for (int k = 1; k < 96; ++k) + { + Nat224.copy(d1, d0); + Nat224.copy(e1, e0); + + RS(d1, e1, f1, t); + + if (Nat224.isZero(d1)) + { + Mod.invert(SecP224R1Field.P, e0, t); + SecP224R1Field.multiply(t, d0, t); + return true; + } + } + + return false; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java new file mode 100644 index 000000000..d44f2f8ff --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP224R1Point.java @@ -0,0 +1,308 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat224; + +public class SecP224R1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP224R1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP224R1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Y1 = (SecP224R1FieldElement)this.y; + SecP224R1FieldElement X2 = (SecP224R1FieldElement)b.getXCoord(), Y2 = (SecP224R1FieldElement)b.getYCoord(); + + SecP224R1FieldElement Z1 = (SecP224R1FieldElement)this.zs[0]; + SecP224R1FieldElement Z2 = (SecP224R1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat224.createExt(); + int[] t2 = Nat224.create(); + int[] t3 = Nat224.create(); + int[] t4 = Nat224.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP224R1Field.square(Z1.x, S2); + + U2 = t2; + SecP224R1Field.multiply(S2, X2.x, U2); + + SecP224R1Field.multiply(S2, Z1.x, S2); + SecP224R1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP224R1Field.square(Z2.x, S1); + + U1 = tt1; + SecP224R1Field.multiply(S1, X1.x, U1); + + SecP224R1Field.multiply(S1, Z2.x, S1); + SecP224R1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat224.create(); + SecP224R1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP224R1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat224.isZero(H)) + { + if (Nat224.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP224R1Field.square(H, HSquared); + + int[] G = Nat224.create(); + SecP224R1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP224R1Field.multiply(HSquared, U1, V); + + SecP224R1Field.negate(G, G); + Nat224.mul(S1, G, tt1); + + c = Nat224.addBothTo(V, V, G); + SecP224R1Field.reduce32(c, G); + + SecP224R1FieldElement X3 = new SecP224R1FieldElement(t4); + SecP224R1Field.square(R, X3.x); + SecP224R1Field.subtract(X3.x, G, X3.x); + + SecP224R1FieldElement Y3 = new SecP224R1FieldElement(G); + SecP224R1Field.subtract(V, X3.x, Y3.x); + SecP224R1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP224R1Field.reduce(tt1, Y3.x); + + SecP224R1FieldElement Z3 = new SecP224R1FieldElement(H); + if (!Z1IsOne) + { + SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP224R1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP224R1Point(curve, X3, Y3, zs, this.withCompression); + } + + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP224R1FieldElement Y1 = (SecP224R1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.x, Z1 = (SecP224R1FieldElement)this.zs[0]; + + int c; + int[] t1 = Nat224.create(); + int[] t2 = Nat224.create(); + + int[] Y1Squared = Nat224.create(); + SecP224R1Field.square(Y1.x, Y1Squared); + + int[] T = Nat224.create(); + SecP224R1Field.square(Y1Squared, T); + + boolean Z1IsOne = Z1.isOne(); + + int[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP224R1Field.square(Z1.x, Z1Squared); + } + + SecP224R1Field.subtract(X1.x, Z1Squared, t1); + + int[] M = t2; + SecP224R1Field.add(X1.x, Z1Squared, M); + SecP224R1Field.multiply(M, t1, M); + c = Nat224.addBothTo(M, M, M); + SecP224R1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP224R1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(7, S, 2, 0); + SecP224R1Field.reduce32(c, S); + + c = Nat.shiftUpBits(7, T, 3, 0, t1); + SecP224R1Field.reduce32(c, t1); + + SecP224R1FieldElement X3 = new SecP224R1FieldElement(T); + SecP224R1Field.square(M, X3.x); + SecP224R1Field.subtract(X3.x, S, X3.x); + SecP224R1Field.subtract(X3.x, S, X3.x); + + SecP224R1FieldElement Y3 = new SecP224R1FieldElement(S); + SecP224R1Field.subtract(S, X3.x, Y3.x); + SecP224R1Field.multiply(Y3.x, M, Y3.x); + SecP224R1Field.subtract(Y3.x, t1, Y3.x); + + SecP224R1FieldElement Z3 = new SecP224R1FieldElement(M); + SecP224R1Field.twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP224R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP224R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP224R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java new file mode 100644 index 000000000..85d31cc18 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Curve.java @@ -0,0 +1,78 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP256K1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")); + + private static final int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP256K1Point infinity; + + public SecP256K1Curve() + { + super(q); + + this.infinity = new SecP256K1Point(this, null, null); + + this.a = fromBigInteger(ECConstants.ZERO); + this.b = fromBigInteger(BigInteger.valueOf(7)); + this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")); + this.cofactor = BigInteger.valueOf(1); + this.coord = SECP256K1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP256K1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP256K1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP256K1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP256K1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java new file mode 100644 index 000000000..3aae2f2fa --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Field.java @@ -0,0 +1,179 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat256; + +public class SecP256K1Field +{ + // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 + static final int[] P = new int[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 }; + private static final int P7 = 0xFFFFFFFF; + private static final int PExt15 = 0xFFFFFFFF; + private static final int PInv33 = 0x3D1; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat256.add(x, y, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + Nat.add33To(8, PInv33, z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(16, xx, yy, zz); + if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(16, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(8, x, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + Nat.add33To(8, PInv33, z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat256.fromBigInteger(x); + if (z[7] == P7 && Nat256.gte(z, P)) + { + Nat256.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(8, x, 0, z); + } + else + { + int c = Nat256.add(x, P, z); + Nat.shiftDownBit(8, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat256.mulAddTo(x, y, zz); + if (c != 0 || (zz[15] == PExt15 && Nat.gte(16, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(16, zz, PExtInv.length); + } + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat256.isZero(x)) + { + Nat256.zero(z); + } + else + { + Nat256.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long cc = Nat256.mul33Add(PInv33, xx, 8, xx, 0, z, 0); + int c = Nat256.mul33DWordAdd(PInv33, cc, z, 0); + + // assert c == 0L || c == 1L; + + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + Nat.add33To(8, PInv33, z); + } + } + + public static void reduce32(int x, int[] z) + { + if ((x != 0 && Nat256.mul33WordAdd(PInv33, x, z, 0) != 0) + || (z[7] == P7 && Nat256.gte(z, P))) + { + Nat.add33To(8, PInv33, z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat256.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat256.sub(x, y, z); + if (c != 0) + { + Nat.sub33From(8, PInv33, z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(16, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(16, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(8, x, 0, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + Nat.add33To(8, PInv33, z); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java new file mode 100644 index 000000000..10d8a2655 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1FieldElement.java @@ -0,0 +1,215 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat256; +import org.spongycastle.util.Arrays; + +public class SecP256K1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP256K1Curve.q; + + protected int[] x; + + public SecP256K1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP256K1FieldElement"); + } + + this.x = SecP256K1Field.fromBigInteger(x); + } + + public SecP256K1FieldElement() + { + this.x = Nat256.create(); + } + + protected SecP256K1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat256.isZero(x); + } + + public boolean isOne() + { + return Nat256.isOne(x); + } + + public boolean testBitZero() + { + return Nat256.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat256.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP256K1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256K1Field.add(x, ((SecP256K1FieldElement)b).x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat256.create(); + SecP256K1Field.addOne(x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256K1Field.subtract(x, ((SecP256K1FieldElement)b).x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256K1Field.multiply(x, ((SecP256K1FieldElement)b).x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat256.create(); + Mod.invert(SecP256K1Field.P, ((SecP256K1FieldElement)b).x, z); + SecP256K1Field.multiply(z, x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat256.create(); + SecP256K1Field.negate(x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat256.create(); + SecP256K1Field.square(x, z); + return new SecP256K1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP256K1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat256.create(); + Mod.invert(SecP256K1Field.P, x, z); + return new SecP256K1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + /* + * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2 + * + * Breaking up the exponent's binary representation into "repunits", we get: + * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s} + * + * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits) + * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + int[] x1 = this.x; + if (Nat256.isZero(x1) || Nat256.isOne(x1)) + { + return this; + } + + int[] x2 = Nat256.create(); + SecP256K1Field.square(x1, x2); + SecP256K1Field.multiply(x2, x1, x2); + int[] x3 = Nat256.create(); + SecP256K1Field.square(x2, x3); + SecP256K1Field.multiply(x3, x1, x3); + int[] x6 = Nat256.create(); + SecP256K1Field.squareN(x3, 3, x6); + SecP256K1Field.multiply(x6, x3, x6); + int[] x9 = x6; + SecP256K1Field.squareN(x6, 3, x9); + SecP256K1Field.multiply(x9, x3, x9); + int[] x11 = x9; + SecP256K1Field.squareN(x9, 2, x11); + SecP256K1Field.multiply(x11, x2, x11); + int[] x22 = Nat256.create(); + SecP256K1Field.squareN(x11, 11, x22); + SecP256K1Field.multiply(x22, x11, x22); + int[] x44 = x11; + SecP256K1Field.squareN(x22, 22, x44); + SecP256K1Field.multiply(x44, x22, x44); + int[] x88 = Nat256.create(); + SecP256K1Field.squareN(x44, 44, x88); + SecP256K1Field.multiply(x88, x44, x88); + int[] x176 = Nat256.create(); + SecP256K1Field.squareN(x88, 88, x176); + SecP256K1Field.multiply(x176, x88, x176); + int[] x220 = x88; + SecP256K1Field.squareN(x176, 44, x220); + SecP256K1Field.multiply(x220, x44, x220); + int[] x223 = x44; + SecP256K1Field.squareN(x220, 3, x223); + SecP256K1Field.multiply(x223, x3, x223); + + int[] t1 = x223; + SecP256K1Field.squareN(t1, 23, t1); + SecP256K1Field.multiply(t1, x22, t1); + SecP256K1Field.squareN(t1, 6, t1); + SecP256K1Field.multiply(t1, x2, t1); + SecP256K1Field.squareN(t1, 2, t1); + + int[] t2 = x2; + SecP256K1Field.square(t1, t2); + + return Nat256.eq(x1, t2) ? new SecP256K1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP256K1FieldElement)) + { + return false; + } + + SecP256K1FieldElement o = (SecP256K1FieldElement)other; + return Nat256.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 8); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java new file mode 100644 index 000000000..fa9394313 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256K1Point.java @@ -0,0 +1,298 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat256; + +public class SecP256K1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP256K1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, + boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP256K1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + // B.3 pg 62 + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Y1 = (SecP256K1FieldElement)this.y; + SecP256K1FieldElement X2 = (SecP256K1FieldElement)b.getXCoord(), Y2 = (SecP256K1FieldElement)b.getYCoord(); + + SecP256K1FieldElement Z1 = (SecP256K1FieldElement)this.zs[0]; + SecP256K1FieldElement Z2 = (SecP256K1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat256.createExt(); + int[] t2 = Nat256.create(); + int[] t3 = Nat256.create(); + int[] t4 = Nat256.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP256K1Field.square(Z1.x, S2); + + U2 = t2; + SecP256K1Field.multiply(S2, X2.x, U2); + + SecP256K1Field.multiply(S2, Z1.x, S2); + SecP256K1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP256K1Field.square(Z2.x, S1); + + U1 = tt1; + SecP256K1Field.multiply(S1, X1.x, U1); + + SecP256K1Field.multiply(S1, Z2.x, S1); + SecP256K1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat256.create(); + SecP256K1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP256K1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat256.isZero(H)) + { + if (Nat256.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP256K1Field.square(H, HSquared); + + int[] G = Nat256.create(); + SecP256K1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP256K1Field.multiply(HSquared, U1, V); + + SecP256K1Field.negate(G, G); + Nat256.mul(S1, G, tt1); + + c = Nat256.addBothTo(V, V, G); + SecP256K1Field.reduce32(c, G); + + SecP256K1FieldElement X3 = new SecP256K1FieldElement(t4); + SecP256K1Field.square(R, X3.x); + SecP256K1Field.subtract(X3.x, G, X3.x); + + SecP256K1FieldElement Y3 = new SecP256K1FieldElement(G); + SecP256K1Field.subtract(V, X3.x, Y3.x); + SecP256K1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP256K1Field.reduce(tt1, Y3.x); + + SecP256K1FieldElement Z3 = new SecP256K1FieldElement(H); + if (!Z1IsOne) + { + SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP256K1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[] { Z3 }; + + return new SecP256K1Point(curve, X3, Y3, zs, this.withCompression); + } + + // B.3 pg 62 + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP256K1FieldElement Y1 = (SecP256K1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.x, Z1 = (SecP256K1FieldElement)this.zs[0]; + + int c; + + int[] Y1Squared = Nat256.create(); + SecP256K1Field.square(Y1.x, Y1Squared); + + int[] T = Nat256.create(); + SecP256K1Field.square(Y1Squared, T); + + int[] M = Nat256.create(); + SecP256K1Field.square(X1.x, M); + c = Nat256.addBothTo(M, M, M); + SecP256K1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP256K1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(8, S, 2, 0); + SecP256K1Field.reduce32(c, S); + + int[] t1 = Nat256.create(); + c = Nat.shiftUpBits(8, T, 3, 0, t1); + SecP256K1Field.reduce32(c, t1); + + SecP256K1FieldElement X3 = new SecP256K1FieldElement(T); + SecP256K1Field.square(M, X3.x); + SecP256K1Field.subtract(X3.x, S, X3.x); + SecP256K1Field.subtract(X3.x, S, X3.x); + + SecP256K1FieldElement Y3 = new SecP256K1FieldElement(S); + SecP256K1Field.subtract(S, X3.x, Y3.x); + SecP256K1Field.multiply(Y3.x, M, Y3.x); + SecP256K1Field.subtract(Y3.x, t1, Y3.x); + + SecP256K1FieldElement Z3 = new SecP256K1FieldElement(M); + SecP256K1Field.twice(Y1.x, Z3.x); + if (!Z1.isOne()) + { + SecP256K1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP256K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP256K1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java new file mode 100644 index 000000000..f856bb34e --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Curve.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP256R1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")); + + private static final int SecP256R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP256R1Point infinity; + + public SecP256R1Curve() + { + super(q); + + this.infinity = new SecP256R1Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"))); + this.order = new BigInteger(1, Hex.decode("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP256R1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP256R1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP256R1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP256R1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP256R1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java new file mode 100644 index 000000000..78c15d174 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Field.java @@ -0,0 +1,312 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat256; + +public class SecP256R1Field +{ + private static final long M = 0xFFFFFFFFL; + + // 2^256 - 2^224 + 2^192 + 2^96 - 1 + static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE, + 0x00000002, 0xFFFFFFFE }; + private static final int P7 = 0xFFFFFFFF; + private static final int PExt15 = 0xFFFFFFFF; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat256.add(x, y, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(16, xx, yy, zz); + if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt))) + { + Nat.subFrom(16, PExt, zz); + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(8, x, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + addPInvTo(z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat256.fromBigInteger(x); + if (z[7] == P7 && Nat256.gte(z, P)) + { + Nat256.subFrom(P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(8, x, 0, z); + } + else + { + int c = Nat256.add(x, P, z); + Nat.shiftDownBit(8, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.mul(x, y, tt); + reduce(tt, z); + } + + public static void multiplyAddToExt(int[] x, int[] y, int[] zz) + { + int c = Nat256.mulAddTo(x, y, zz); + if (c != 0 || ((zz[15] & PExt15) == PExt15 && Nat.gte(16, zz, PExt))) + { + Nat.subFrom(16, PExt, zz); + } + } + + public static void negate(int[] x, int[] z) + { + if (Nat256.isZero(x)) + { + Nat256.zero(z); + } + else + { + Nat256.sub(P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long xx08 = xx[8] & M, xx09 = xx[9] & M, xx10 = xx[10] & M, xx11 = xx[11] & M; + long xx12 = xx[12] & M, xx13 = xx[13] & M, xx14 = xx[14] & M, xx15 = xx[15] & M; + + final long n = 6; + + xx08 -= n; + + long t0 = xx08 + xx09; + long t1 = xx09 + xx10; + long t2 = xx10 + xx11 - xx15; + long t3 = xx11 + xx12; + long t4 = xx12 + xx13; + long t5 = xx13 + xx14; + long t6 = xx14 + xx15; + + long cc = 0; + cc += (xx[0] & M) + t0 - t3 - t5; + z[0] = (int)cc; + cc >>= 32; + cc += (xx[1] & M) + t1 - t4 - t6; + z[1] = (int)cc; + cc >>= 32; + cc += (xx[2] & M) + t2 - t5; + z[2] = (int)cc; + cc >>= 32; + cc += (xx[3] & M) + (t3 << 1) + xx13 - xx15 - t0; + z[3] = (int)cc; + cc >>= 32; + cc += (xx[4] & M) + (t4 << 1) + xx14 - t1; + z[4] = (int)cc; + cc >>= 32; + cc += (xx[5] & M) + (t5 << 1) - t2; + z[5] = (int)cc; + cc >>= 32; + cc += (xx[6] & M) + (t6 << 1) + t5 - t0; + z[6] = (int)cc; + cc >>= 32; + cc += (xx[7] & M) + (xx15 << 1) + xx08 - t2 - t4; + z[7] = (int)cc; + cc >>= 32; + cc += n; + +// assert cc >= 0; + + reduce32((int)cc, z); + } + + public static void reduce32(int x, int[] z) + { + long cc = 0; + + if (x != 0) + { + long xx08 = x & M; + + cc += (z[0] & M) + xx08; + z[0] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[1] & M); + z[1] = (int)cc; + cc >>= 32; + cc += (z[2] & M); + z[2] = (int)cc; + cc >>= 32; + } + cc += (z[3] & M) - xx08; + z[3] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[4] & M); + z[4] = (int)cc; + cc >>= 32; + cc += (z[5] & M); + z[5] = (int)cc; + cc >>= 32; + } + cc += (z[6] & M) - xx08; + z[6] = (int)cc; + cc >>= 32; + cc += (z[7] & M) + xx08; + z[7] = (int)cc; + cc >>= 32; + +// assert cc == 0 || cc == 1; + } + + if (cc != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + addPInvTo(z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat256.createExt(); + Nat256.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat256.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat256.sub(x, y, z); + if (c != 0) + { + subPInvFrom(z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(16, xx, yy, zz); + if (c != 0) + { + Nat.addTo(16, PExt, zz); + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(8, x, 0, z); + if (c != 0 || (z[7] == P7 && Nat256.gte(z, P))) + { + addPInvTo(z); + } + } + + private static void addPInvTo(int[] z) + { + long c = (z[0] & M) + 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) - 1; + z[3] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M); + z[5] = (int)c; + c >>= 32; + } + c += (z[6] & M) - 1; + z[6] = (int)c; + c >>= 32; + c += (z[7] & M) + 1; + z[7] = (int)c; +// c >>= 32; + } + + private static void subPInvFrom(int[] z) + { + long c = (z[0] & M) - 1; + z[0] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) + 1; + z[3] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M); + z[5] = (int)c; + c >>= 32; + } + c += (z[6] & M) + 1; + z[6] = (int)c; + c >>= 32; + c += (z[7] & M) - 1; + z[7] = (int)c; +// c >>= 32; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java new file mode 100644 index 000000000..ddbab1a32 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1FieldElement.java @@ -0,0 +1,189 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat256; +import org.spongycastle.util.Arrays; + +public class SecP256R1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP256R1Curve.q; + + protected int[] x; + + public SecP256R1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP256R1FieldElement"); + } + + this.x = SecP256R1Field.fromBigInteger(x); + } + + public SecP256R1FieldElement() + { + this.x = Nat256.create(); + } + + protected SecP256R1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat256.isZero(x); + } + + public boolean isOne() + { + return Nat256.isOne(x); + } + + public boolean testBitZero() + { + return Nat256.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat256.toBigInteger(x); + } + + public String getFieldName() + { + return "SecP256R1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256R1Field.add(x, ((SecP256R1FieldElement)b).x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat256.create(); + SecP256R1Field.addOne(x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256R1Field.subtract(x, ((SecP256R1FieldElement)b).x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat256.create(); + SecP256R1Field.multiply(x, ((SecP256R1FieldElement)b).x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat256.create(); + Mod.invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z); + SecP256R1Field.multiply(z, x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat256.create(); + SecP256R1Field.negate(x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat256.create(); + SecP256R1Field.square(x, z); + return new SecP256R1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP256R1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat256.create(); + Mod.invert(SecP256R1Field.P, x, z); + return new SecP256R1FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94 + + int[] x1 = this.x; + if (Nat256.isZero(x1) || Nat256.isOne(x1)) + { + return this; + } + + int[] t1 = Nat256.create(); + int[] t2 = Nat256.create(); + + SecP256R1Field.square(x1, t1); + SecP256R1Field.multiply(t1, x1, t1); + + SecP256R1Field.squareN(t1, 2, t2); + SecP256R1Field.multiply(t2, t1, t2); + + SecP256R1Field.squareN(t2, 4, t1); + SecP256R1Field.multiply(t1, t2, t1); + + SecP256R1Field.squareN(t1, 8, t2); + SecP256R1Field.multiply(t2, t1, t2); + + SecP256R1Field.squareN(t2, 16, t1); + SecP256R1Field.multiply(t1, t2, t1); + + SecP256R1Field.squareN(t1, 32, t1); + SecP256R1Field.multiply(t1, x1, t1); + + SecP256R1Field.squareN(t1, 96, t1); + SecP256R1Field.multiply(t1, x1, t1); + + SecP256R1Field.squareN(t1, 94, t1); + SecP256R1Field.square(t1, t2); + + return Nat256.eq(x1, t2) ? new SecP256R1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP256R1FieldElement)) + { + return false; + } + + SecP256R1FieldElement o = (SecP256R1FieldElement)other; + return Nat256.eq(x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 8); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java new file mode 100644 index 000000000..8daaf0491 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP256R1Point.java @@ -0,0 +1,308 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat256; + +public class SecP256R1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP256R1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP256R1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Y1 = (SecP256R1FieldElement)this.y; + SecP256R1FieldElement X2 = (SecP256R1FieldElement)b.getXCoord(), Y2 = (SecP256R1FieldElement)b.getYCoord(); + + SecP256R1FieldElement Z1 = (SecP256R1FieldElement)this.zs[0]; + SecP256R1FieldElement Z2 = (SecP256R1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat256.createExt(); + int[] t2 = Nat256.create(); + int[] t3 = Nat256.create(); + int[] t4 = Nat256.create(); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP256R1Field.square(Z1.x, S2); + + U2 = t2; + SecP256R1Field.multiply(S2, X2.x, U2); + + SecP256R1Field.multiply(S2, Z1.x, S2); + SecP256R1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP256R1Field.square(Z2.x, S1); + + U1 = tt1; + SecP256R1Field.multiply(S1, X1.x, U1); + + SecP256R1Field.multiply(S1, Z2.x, S1); + SecP256R1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat256.create(); + SecP256R1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP256R1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat256.isZero(H)) + { + if (Nat256.isZero(R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP256R1Field.square(H, HSquared); + + int[] G = Nat256.create(); + SecP256R1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP256R1Field.multiply(HSquared, U1, V); + + SecP256R1Field.negate(G, G); + Nat256.mul(S1, G, tt1); + + c = Nat256.addBothTo(V, V, G); + SecP256R1Field.reduce32(c, G); + + SecP256R1FieldElement X3 = new SecP256R1FieldElement(t4); + SecP256R1Field.square(R, X3.x); + SecP256R1Field.subtract(X3.x, G, X3.x); + + SecP256R1FieldElement Y3 = new SecP256R1FieldElement(G); + SecP256R1Field.subtract(V, X3.x, Y3.x); + SecP256R1Field.multiplyAddToExt(Y3.x, R, tt1); + SecP256R1Field.reduce(tt1, Y3.x); + + SecP256R1FieldElement Z3 = new SecP256R1FieldElement(H); + if (!Z1IsOne) + { + SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP256R1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP256R1Point(curve, X3, Y3, zs, this.withCompression); + } + + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP256R1FieldElement Y1 = (SecP256R1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.x, Z1 = (SecP256R1FieldElement)this.zs[0]; + + int c; + int[] t1 = Nat256.create(); + int[] t2 = Nat256.create(); + + int[] Y1Squared = Nat256.create(); + SecP256R1Field.square(Y1.x, Y1Squared); + + int[] T = Nat256.create(); + SecP256R1Field.square(Y1Squared, T); + + boolean Z1IsOne = Z1.isOne(); + + int[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP256R1Field.square(Z1.x, Z1Squared); + } + + SecP256R1Field.subtract(X1.x, Z1Squared, t1); + + int[] M = t2; + SecP256R1Field.add(X1.x, Z1Squared, M); + SecP256R1Field.multiply(M, t1, M); + c = Nat256.addBothTo(M, M, M); + SecP256R1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP256R1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(8, S, 2, 0); + SecP256R1Field.reduce32(c, S); + + c = Nat.shiftUpBits(8, T, 3, 0, t1); + SecP256R1Field.reduce32(c, t1); + + SecP256R1FieldElement X3 = new SecP256R1FieldElement(T); + SecP256R1Field.square(M, X3.x); + SecP256R1Field.subtract(X3.x, S, X3.x); + SecP256R1Field.subtract(X3.x, S, X3.x); + + SecP256R1FieldElement Y3 = new SecP256R1FieldElement(S); + SecP256R1Field.subtract(S, X3.x, Y3.x); + SecP256R1Field.multiply(Y3.x, M, Y3.x); + SecP256R1Field.subtract(Y3.x, t1, Y3.x); + + SecP256R1FieldElement Z3 = new SecP256R1FieldElement(M); + SecP256R1Field.twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP256R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP256R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP256R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java new file mode 100644 index 000000000..cb5bab249 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Curve.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP384R1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")); + + private static final int SecP384R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP384R1Point infinity; + + public SecP384R1Curve() + { + super(q); + + this.infinity = new SecP384R1Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"))); + this.order = new BigInteger(1, Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP384R1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP384R1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP384R1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP384R1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP384R1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java new file mode 100644 index 000000000..d3b78762f --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Field.java @@ -0,0 +1,295 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat384; + +public class SecP384R1Field +{ + private static final long M = 0xFFFFFFFFL; + + // 2^384 - 2^128 - 2^96 + 2^32 - 1 + static final int[] P = new int[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + static final int[] PExt = new int[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE, + 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000, + 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + private static final int[] PExtInv = new int[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001, + 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF, + 0x00000001, 0x00000002 }; + private static final int P11 = 0xFFFFFFFF; + private static final int PExt23 = 0xFFFFFFFF; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat.add(12, x, y, z); + if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) + { + addPInvTo(z); + } + } + + public static void addExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.add(24, xx, yy, zz); + if (c != 0 || (zz[23] == PExt23 && Nat.gte(24, zz, PExt))) + { + if (Nat.addTo(PExtInv.length, PExtInv, zz) != 0) + { + Nat.incAt(24, zz, PExtInv.length); + } + } + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(12, x, z); + if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) + { + addPInvTo(z); + } + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat.fromBigInteger(384, x); + if (z[11] == P11 && Nat.gte(12, z, P)) + { + Nat.subFrom(12, P, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + if ((x[0] & 1) == 0) + { + Nat.shiftDownBit(12, x, 0, z); + } + else + { + int c = Nat.add(12, x, P, z); + Nat.shiftDownBit(12, z, c); + } + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat.create(24); + Nat384.mul(x, y, tt); + reduce(tt, z); + } + + public static void negate(int[] x, int[] z) + { + if (Nat.isZero(12, x)) + { + Nat.zero(12, z); + } + else + { + Nat.sub(12, P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { + long xx16 = xx[16] & M, xx17 = xx[17] & M, xx18 = xx[18] & M, xx19 = xx[19] & M; + long xx20 = xx[20] & M, xx21 = xx[21] & M, xx22 = xx[22] & M, xx23 = xx[23] & M; + + final long n = 1; + + long t0 = (xx[12] & M) + xx20 - n; + long t1 = (xx[13] & M) + xx22; + long t2 = (xx[14] & M) + xx22 + xx23; + long t3 = (xx[15] & M) + xx23; + long t4 = xx17 + xx21; + long t5 = xx21 - xx23; + long t6 = xx22 - xx23; + + long cc = 0; + cc += (xx[0] & M) + t0 + t5; + z[0] = (int)cc; + cc >>= 32; + cc += (xx[1] & M) + xx23 - t0 + t1; + z[1] = (int)cc; + cc >>= 32; + cc += (xx[2] & M) - xx21 - t1 + t2; + z[2] = (int)cc; + cc >>= 32; + cc += (xx[3] & M) + t0 - t2 + t3 + t5; + z[3] = (int)cc; + cc >>= 32; + cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5; + z[4] = (int)cc; + cc >>= 32; + cc += (xx[5] & M) - xx16 + t1 + t2 + t4; + z[5] = (int)cc; + cc >>= 32; + cc += (xx[6] & M) + xx18 - xx17 + t2 + t3; + z[6] = (int)cc; + cc >>= 32; + cc += (xx[7] & M) + xx16 + xx19 - xx18 + t3; + z[7] = (int)cc; + cc >>= 32; + cc += (xx[8] & M) + xx16 + xx17 + xx20 - xx19; + z[8] = (int)cc; + cc >>= 32; + cc += (xx[9] & M) + xx18 - xx20 + t4; + z[9] = (int)cc; + cc >>= 32; + cc += (xx[10] & M) + xx18 + xx19 - t5 + t6; + z[10] = (int)cc; + cc >>= 32; + cc += (xx[11] & M) + xx19 + xx20 - t6; + z[11] = (int)cc; + cc >>= 32; + cc += n; + +// assert cc >= 0; + + reduce32((int)cc, z); + } + + public static void reduce32(int x, int[] z) + { + long cc = 0; + + if (x != 0) + { + long xx12 = x & M; + + cc += (z[0] & M) + xx12; + z[0] = (int)cc; + cc >>= 32; + cc += (z[1] & M) - xx12; + z[1] = (int)cc; + cc >>= 32; + if (cc != 0) + { + cc += (z[2] & M); + z[2] = (int)cc; + cc >>= 32; + } + cc += (z[3] & M) + xx12; + z[3] = (int)cc; + cc >>= 32; + cc += (z[4] & M) + xx12; + z[4] = (int)cc; + cc >>= 32; + +// assert cc == 0 || cc == 1; + } + + if ((cc != 0 && Nat.incAt(12, z, 5) != 0) + || (z[11] == P11 && Nat.gte(12, z, P))) + { + addPInvTo(z); + } + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat.create(24); + Nat384.square(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat.create(24); + Nat384.square(x, tt); + reduce(tt, z); + + while (--n > 0) + { + Nat384.square(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat.sub(12, x, y, z); + if (c != 0) + { + subPInvFrom(z); + } + } + + public static void subtractExt(int[] xx, int[] yy, int[] zz) + { + int c = Nat.sub(24, xx, yy, zz); + if (c != 0) + { + if (Nat.subFrom(PExtInv.length, PExtInv, zz) != 0) + { + Nat.decAt(24, zz, PExtInv.length); + } + } + } + + public static void twice(int[] x, int[] z) + { + int c = Nat.shiftUpBit(12, x, 0, z); + if (c != 0 || (z[11] == P11 && Nat.gte(12, z, P))) + { + addPInvTo(z); + } + } + + private static void addPInvTo(int[] z) + { + long c = (z[0] & M) + 1; + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - 1; + z[1] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) + 1; + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) + 1; + z[4] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.incAt(12, z, 5); + } + } + + private static void subPInvFrom(int[] z) + { + long c = (z[0] & M) - 1; + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) + 1; + z[1] = (int)c; + c >>= 32; + if (c != 0) + { + c += (z[2] & M); + z[2] = (int)c; + c >>= 32; + } + c += (z[3] & M) - 1; + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - 1; + z[4] = (int)c; + c >>= 32; + if (c != 0) + { + Nat.decAt(12, z, 5); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java new file mode 100644 index 000000000..3203bda94 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1FieldElement.java @@ -0,0 +1,211 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.util.Arrays; + +public class SecP384R1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP384R1Curve.q; + + protected int[] x; + + public SecP384R1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP384R1FieldElement"); + } + + this.x = SecP384R1Field.fromBigInteger(x); + } + + public SecP384R1FieldElement() + { + this.x = Nat.create(12); + } + + protected SecP384R1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat.isZero(12, x); + } + + public boolean isOne() + { + return Nat.isOne(12, x); + } + + public boolean testBitZero() + { + return Nat.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat.toBigInteger(12, x); + } + + public String getFieldName() + { + return "SecP384R1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat.create(12); + SecP384R1Field.add(x, ((SecP384R1FieldElement)b).x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat.create(12); + SecP384R1Field.addOne(x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat.create(12); + SecP384R1Field.subtract(x, ((SecP384R1FieldElement)b).x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat.create(12); + SecP384R1Field.multiply(x, ((SecP384R1FieldElement)b).x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat.create(12); + Mod.invert(SecP384R1Field.P, ((SecP384R1FieldElement)b).x, z); + SecP384R1Field.multiply(z, x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat.create(12); + SecP384R1Field.negate(x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat.create(12); + SecP384R1Field.square(x, z); + return new SecP384R1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP384R1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat.create(12); + Mod.invert(SecP384R1Field.P, x, z); + return new SecP384R1FieldElement(z); + } + + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30 + + int[] x1 = this.x; + if (Nat.isZero(12, x1) || Nat.isOne(12, x1)) + { + return this; + } + + int[] t1 = Nat.create(12); + int[] t2 = Nat.create(12); + int[] t3 = Nat.create(12); + int[] t4 = Nat.create(12); + + SecP384R1Field.square(x1, t1); + SecP384R1Field.multiply(t1, x1, t1); + + SecP384R1Field.squareN(t1, 2, t2); + SecP384R1Field.multiply(t2, t1, t2); + + SecP384R1Field.square(t2, t2); + SecP384R1Field.multiply(t2, x1, t2); + + SecP384R1Field.squareN(t2, 5, t3); + SecP384R1Field.multiply(t3, t2, t3); + + SecP384R1Field.squareN(t3, 5, t4); + SecP384R1Field.multiply(t4, t2, t4); + + SecP384R1Field.squareN(t4, 15, t2); + SecP384R1Field.multiply(t2, t4, t2); + + SecP384R1Field.squareN(t2, 2, t3); + SecP384R1Field.multiply(t1, t3, t1); + + SecP384R1Field.squareN(t3, 28, t3); + SecP384R1Field.multiply(t2, t3, t2); + + SecP384R1Field.squareN(t2, 60, t3); + SecP384R1Field.multiply(t3, t2, t3); + + int[] r = t2; + + SecP384R1Field.squareN(t3, 120, r); + SecP384R1Field.multiply(r, t3, r); + + SecP384R1Field.squareN(r, 15, r); + SecP384R1Field.multiply(r, t4, r); + + SecP384R1Field.squareN(r, 33, r); + SecP384R1Field.multiply(r, t1, r); + + SecP384R1Field.squareN(r, 64, r); + SecP384R1Field.multiply(r, x1, r); + + SecP384R1Field.squareN(r, 30, t1); + SecP384R1Field.square(t1, t2); + + return Nat.eq(12, x1, t2) ? new SecP384R1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP384R1FieldElement)) + { + return false; + } + + SecP384R1FieldElement o = (SecP384R1FieldElement)other; + return Nat.eq(12, x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 12); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java new file mode 100644 index 000000000..47e5c793f --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP384R1Point.java @@ -0,0 +1,309 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat384; + +public class SecP384R1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP384R1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP384R1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Y1 = (SecP384R1FieldElement)this.y; + SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.getXCoord(), Y2 = (SecP384R1FieldElement)b.getYCoord(); + + SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.zs[0]; + SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.getZCoord(0); + + int c; + int[] tt1 = Nat.create(24); + int[] tt2 = Nat.create(24); + int[] t3 = Nat.create(12); + int[] t4 = Nat.create(12); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP384R1Field.square(Z1.x, S2); + + U2 = tt2; + SecP384R1Field.multiply(S2, X2.x, U2); + + SecP384R1Field.multiply(S2, Z1.x, S2); + SecP384R1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP384R1Field.square(Z2.x, S1); + + U1 = tt1; + SecP384R1Field.multiply(S1, X1.x, U1); + + SecP384R1Field.multiply(S1, Z2.x, S1); + SecP384R1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat.create(12); + SecP384R1Field.subtract(U1, U2, H); + + int[] R = Nat.create(12); + SecP384R1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat.isZero(12, H)) + { + if (Nat.isZero(12, R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP384R1Field.square(H, HSquared); + + int[] G = Nat.create(12); + SecP384R1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP384R1Field.multiply(HSquared, U1, V); + + SecP384R1Field.negate(G, G); + Nat384.mul(S1, G, tt1); + + c = Nat.addBothTo(12, V, V, G); + SecP384R1Field.reduce32(c, G); + + SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4); + SecP384R1Field.square(R, X3.x); + SecP384R1Field.subtract(X3.x, G, X3.x); + + SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G); + SecP384R1Field.subtract(V, X3.x, Y3.x); + Nat384.mul(Y3.x, R, tt2); + SecP384R1Field.addExt(tt1, tt2, tt1); + SecP384R1Field.reduce(tt1, Y3.x); + + SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H); + if (!Z1IsOne) + { + SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP384R1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP384R1Point(curve, X3, Y3, zs, this.withCompression); + } + + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.x, Z1 = (SecP384R1FieldElement)this.zs[0]; + + int c; + int[] t1 = Nat.create(12); + int[] t2 = Nat.create(12); + + int[] Y1Squared = Nat.create(12); + SecP384R1Field.square(Y1.x, Y1Squared); + + int[] T = Nat.create(12); + SecP384R1Field.square(Y1Squared, T); + + boolean Z1IsOne = Z1.isOne(); + + int[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP384R1Field.square(Z1.x, Z1Squared); + } + + SecP384R1Field.subtract(X1.x, Z1Squared, t1); + + int[] M = t2; + SecP384R1Field.add(X1.x, Z1Squared, M); + SecP384R1Field.multiply(M, t1, M); + c = Nat.addBothTo(12, M, M, M); + SecP384R1Field.reduce32(c, M); + + int[] S = Y1Squared; + SecP384R1Field.multiply(Y1Squared, X1.x, S); + c = Nat.shiftUpBits(12, S, 2, 0); + SecP384R1Field.reduce32(c, S); + + c = Nat.shiftUpBits(12, T, 3, 0, t1); + SecP384R1Field.reduce32(c, t1); + + SecP384R1FieldElement X3 = new SecP384R1FieldElement(T); + SecP384R1Field.square(M, X3.x); + SecP384R1Field.subtract(X3.x, S, X3.x); + SecP384R1Field.subtract(X3.x, S, X3.x); + + SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S); + SecP384R1Field.subtract(S, X3.x, Y3.x); + SecP384R1Field.multiply(Y3.x, M, Y3.x); + SecP384R1Field.subtract(Y3.x, t1, Y3.x); + + SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M); + SecP384R1Field.twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP384R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP384R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java new file mode 100644 index 000000000..fb53cfbb8 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Curve.java @@ -0,0 +1,80 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.encoders.Hex; + +public class SecP521R1Curve extends ECCurve.AbstractFp +{ + public static final BigInteger q = new BigInteger(1, + Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")); + + private static final int SecP521R1_DEFAULT_COORDS = COORD_JACOBIAN; + + protected SecP521R1Point infinity; + + public SecP521R1Curve() + { + super(q); + + this.infinity = new SecP521R1Point(this, null, null); + + this.a = fromBigInteger(new BigInteger(1, + Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC"))); + this.b = fromBigInteger(new BigInteger(1, + Hex.decode("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"))); + this.order = new BigInteger(1, Hex.decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409")); + this.cofactor = BigInteger.valueOf(1); + + this.coord = SecP521R1_DEFAULT_COORDS; + } + + protected ECCurve cloneCurve() + { + return new SecP521R1Curve(); + } + + public boolean supportsCoordinateSystem(int coord) + { + switch (coord) + { + case COORD_JACOBIAN: + return true; + default: + return false; + } + } + + public BigInteger getQ() + { + return q; + } + + public int getFieldSize() + { + return q.bitLength(); + } + + public ECFieldElement fromBigInteger(BigInteger x) + { + return new SecP521R1FieldElement(x); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, boolean withCompression) + { + return new SecP521R1Point(this, x, y, withCompression); + } + + protected ECPoint createRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + return new SecP521R1Point(this, x, y, zs, withCompression); + } + + public ECPoint getInfinity() + { + return infinity; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java new file mode 100644 index 000000000..5328a510a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Field.java @@ -0,0 +1,156 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.raw.Nat; +import org.spongycastle.math.raw.Nat512; + +public class SecP521R1Field +{ + // 2^521 - 1 + static final int[] P = new int[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF }; + private static final int P16 = 0x1FF; + + public static void add(int[] x, int[] y, int[] z) + { + int c = Nat.add(16, x, y, z) + x[16] + y[16]; + if (c > P16 || (c == P16 && Nat.eq(16, z, P))) + { + c += Nat.inc(16, z); + c &= P16; + } + z[16] = c; + } + + public static void addOne(int[] x, int[] z) + { + int c = Nat.inc(16, x, z) + x[16]; + if (c > P16 || (c == P16 && Nat.eq(16, z, P))) + { + c += Nat.inc(16, z); + c &= P16; + } + z[16] = c; + } + + public static int[] fromBigInteger(BigInteger x) + { + int[] z = Nat.fromBigInteger(521, x); + if (Nat.eq(17, z, P)) + { + Nat.zero(17, z); + } + return z; + } + + public static void half(int[] x, int[] z) + { + int x16 = x[16]; + int c = Nat.shiftDownBit(16, x, x16, z); + z[16] = (x16 >>> 1) | (c >>> 23); + } + + public static void multiply(int[] x, int[] y, int[] z) + { + int[] tt = Nat.create(33); + implMultiply(x, y, tt); + reduce(tt, z); + } + + public static void negate(int[] x, int[] z) + { + if (Nat.isZero(17, x)) + { + Nat.zero(17, z); + } + else + { + Nat.sub(17, P, x, z); + } + } + + public static void reduce(int[] xx, int[] z) + { +// assert xx[32] >>> 18 == 0; + + int xx32 = xx[32]; + int c = Nat.shiftDownBits(16, xx, 16, 9, xx32, z, 0) >>> 23; + c += xx32 >>> 9; + c += Nat.addTo(16, xx, z); + if (c > P16 || (c == P16 && Nat.eq(16, z, P))) + { + c += Nat.inc(16, z); + c &= P16; + } + z[16] = c; + } + + public static void reduce23(int[] z) + { + int z16 = z[16]; + int c = Nat.addWordTo(16, z16 >>> 9, z) + (z16 & P16); + if (c > P16 || (c == P16 && Nat.eq(16, z, P))) + { + c += Nat.inc(16, z); + c &= P16; + } + z[16] = c; + } + + public static void square(int[] x, int[] z) + { + int[] tt = Nat.create(33); + implSquare(x, tt); + reduce(tt, z); + } + + public static void squareN(int[] x, int n, int[] z) + { +// assert n > 0; + + int[] tt = Nat.create(33); + implSquare(x, tt); + reduce(tt, z); + + while (--n > 0) + { + implSquare(z, tt); + reduce(tt, z); + } + } + + public static void subtract(int[] x, int[] y, int[] z) + { + int c = Nat.sub(16, x, y, z) + x[16] - y[16]; + if (c < 0) + { + c += Nat.dec(16, z); + c &= P16; + } + z[16] = c; + } + + public static void twice(int[] x, int[] z) + { + int x16 = x[16]; + int c = Nat.shiftUpBit(16, x, x16 << 23, z) | (x16 << 1); + z[16] = c & P16; + } + + protected static void implMultiply(int[] x, int[] y, int[] zz) + { + Nat512.mul(x, y, zz); + + int x16 = x[16], y16 = y[16]; + zz[32] = Nat.mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16); + } + + protected static void implSquare(int[] x, int[] zz) + { + Nat512.square(x, zz); + + int x16 = x[16]; + zz[32] = Nat.mulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java new file mode 100644 index 000000000..b0b92b6e9 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1FieldElement.java @@ -0,0 +1,169 @@ +package org.spongycastle.math.ec.custom.sec; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.raw.Mod; +import org.spongycastle.math.raw.Nat; +import org.spongycastle.util.Arrays; + +public class SecP521R1FieldElement extends ECFieldElement +{ + public static final BigInteger Q = SecP521R1Curve.q; + + protected int[] x; + + public SecP521R1FieldElement(BigInteger x) + { + if (x == null || x.signum() < 0 || x.compareTo(Q) >= 0) + { + throw new IllegalArgumentException("x value invalid for SecP521R1FieldElement"); + } + + this.x = SecP521R1Field.fromBigInteger(x); + } + + public SecP521R1FieldElement() + { + this.x = Nat.create(17); + } + + protected SecP521R1FieldElement(int[] x) + { + this.x = x; + } + + public boolean isZero() + { + return Nat.isZero(17, x); + } + + public boolean isOne() + { + return Nat.isOne(17, x); + } + + public boolean testBitZero() + { + return Nat.getBit(x, 0) == 1; + } + + public BigInteger toBigInteger() + { + return Nat.toBigInteger(17, x); + } + + public String getFieldName() + { + return "SecP521R1Field"; + } + + public int getFieldSize() + { + return Q.bitLength(); + } + + public ECFieldElement add(ECFieldElement b) + { + int[] z = Nat.create(17); + SecP521R1Field.add(x, ((SecP521R1FieldElement)b).x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement addOne() + { + int[] z = Nat.create(17); + SecP521R1Field.addOne(x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement subtract(ECFieldElement b) + { + int[] z = Nat.create(17); + SecP521R1Field.subtract(x, ((SecP521R1FieldElement)b).x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement multiply(ECFieldElement b) + { + int[] z = Nat.create(17); + SecP521R1Field.multiply(x, ((SecP521R1FieldElement)b).x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement divide(ECFieldElement b) + { +// return multiply(b.invert()); + int[] z = Nat.create(17); + Mod.invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z); + SecP521R1Field.multiply(z, x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement negate() + { + int[] z = Nat.create(17); + SecP521R1Field.negate(x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement square() + { + int[] z = Nat.create(17); + SecP521R1Field.square(x, z); + return new SecP521R1FieldElement(z); + } + + public ECFieldElement invert() + { +// return new SecP521R1FieldElement(toBigInteger().modInverse(Q)); + int[] z = Nat.create(17); + Mod.invert(SecP521R1Field.P, x, z); + return new SecP521R1FieldElement(z); + } + + // D.1.4 91 + /** + * return a sqrt root - the routine verifies that the calculation returns the right value - if + * none exists it returns null. + */ + public ECFieldElement sqrt() + { + // Raise this element to the exponent 2^519 + + int[] x1 = this.x; + if (Nat.isZero(17, x1) || Nat.isOne(17, x1)) + { + return this; + } + + int[] t1 = Nat.create(17); + int[] t2 = Nat.create(17); + + SecP521R1Field.squareN(x1, 519, t1); + SecP521R1Field.square(t1, t2); + + return Nat.eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null; + } + + public boolean equals(Object other) + { + if (other == this) + { + return true; + } + + if (!(other instanceof SecP521R1FieldElement)) + { + return false; + } + + SecP521R1FieldElement o = (SecP521R1FieldElement)other; + return Nat.eq(17, x, o.x); + } + + public int hashCode() + { + return Q.hashCode() ^ Arrays.hashCode(x, 0, 17); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java new file mode 100644 index 000000000..c38132b52 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/custom/sec/SecP521R1Point.java @@ -0,0 +1,333 @@ +package org.spongycastle.math.ec.custom.sec; + +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.math.raw.Nat; + +public class SecP521R1Point extends ECPoint.AbstractFp +{ + /** + * 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 + * + * @deprecated Use ECCurve.createPoint to construct points + */ + public SecP521R1Point(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 + * + * @deprecated per-point compression property will be removed, refer + * {@link #getEncoded(boolean)} + */ + public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) + { + super(curve, x, y); + + if ((x == null) != (y == null)) + { + throw new IllegalArgumentException("Exactly one of the field elements is null"); + } + + this.withCompression = withCompression; + } + + SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, boolean withCompression) + { + super(curve, x, y, zs); + + this.withCompression = withCompression; + } + + protected ECPoint detach() + { + return new SecP521R1Point(null, getAffineXCoord(), getAffineYCoord()); + } + + public ECPoint add(ECPoint b) + { + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return this; + } + if (this == b) + { + return twice(); + } + + ECCurve curve = this.getCurve(); + + SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Y1 = (SecP521R1FieldElement)this.y; + SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.getXCoord(), Y2 = (SecP521R1FieldElement)b.getYCoord(); + + SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.zs[0]; + SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.getZCoord(0); + + int[] t1 = Nat.create(17); + int[] t2 = Nat.create(17); + int[] t3 = Nat.create(17); + int[] t4 = Nat.create(17); + + boolean Z1IsOne = Z1.isOne(); + int[] U2, S2; + if (Z1IsOne) + { + U2 = X2.x; + S2 = Y2.x; + } + else + { + S2 = t3; + SecP521R1Field.square(Z1.x, S2); + + U2 = t2; + SecP521R1Field.multiply(S2, X2.x, U2); + + SecP521R1Field.multiply(S2, Z1.x, S2); + SecP521R1Field.multiply(S2, Y2.x, S2); + } + + boolean Z2IsOne = Z2.isOne(); + int[] U1, S1; + if (Z2IsOne) + { + U1 = X1.x; + S1 = Y1.x; + } + else + { + S1 = t4; + SecP521R1Field.square(Z2.x, S1); + + U1 = t1; + SecP521R1Field.multiply(S1, X1.x, U1); + + SecP521R1Field.multiply(S1, Z2.x, S1); + SecP521R1Field.multiply(S1, Y1.x, S1); + } + + int[] H = Nat.create(17); + SecP521R1Field.subtract(U1, U2, H); + + int[] R = t2; + SecP521R1Field.subtract(S1, S2, R); + + // Check if b == this or b == -this + if (Nat.isZero(17, H)) + { + if (Nat.isZero(17, R)) + { + // this == b, i.e. this must be doubled + return this.twice(); + } + + // this == -b, i.e. the result is the point at infinity + return curve.getInfinity(); + } + + int[] HSquared = t3; + SecP521R1Field.square(H, HSquared); + + int[] G = Nat.create(17); + SecP521R1Field.multiply(HSquared, H, G); + + int[] V = t3; + SecP521R1Field.multiply(HSquared, U1, V); + + SecP521R1Field.multiply(S1, G, t1); + + SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4); + SecP521R1Field.square(R, X3.x); + SecP521R1Field.add(X3.x, G, X3.x); + SecP521R1Field.subtract(X3.x, V, X3.x); + SecP521R1Field.subtract(X3.x, V, X3.x); + + SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G); + SecP521R1Field.subtract(V, X3.x, Y3.x); + SecP521R1Field.multiply(Y3.x, R, t2); + SecP521R1Field.subtract(t2, t1, Y3.x); + + SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H); + if (!Z1IsOne) + { + SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + if (!Z2IsOne) + { + SecP521R1Field.multiply(Z3.x, Z2.x, Z3.x); + } + + ECFieldElement[] zs = new ECFieldElement[]{ Z3 }; + + return new SecP521R1Point(curve, X3, Y3, zs, this.withCompression); + } + + public ECPoint twice() + { + if (this.isInfinity()) + { + return this; + } + + ECCurve curve = this.getCurve(); + + SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.y; + if (Y1.isZero()) + { + return curve.getInfinity(); + } + + SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.x, Z1 = (SecP521R1FieldElement)this.zs[0]; + + int[] t1 = Nat.create(17); + int[] t2 = Nat.create(17); + + int[] Y1Squared = Nat.create(17); + SecP521R1Field.square(Y1.x, Y1Squared); + + int[] T = Nat.create(17); + SecP521R1Field.square(Y1Squared, T); + + boolean Z1IsOne = Z1.isOne(); + + int[] Z1Squared = Z1.x; + if (!Z1IsOne) + { + Z1Squared = t2; + SecP521R1Field.square(Z1.x, Z1Squared); + } + + SecP521R1Field.subtract(X1.x, Z1Squared, t1); + + int[] M = t2; + SecP521R1Field.add(X1.x, Z1Squared, M); + SecP521R1Field.multiply(M, t1, M); + Nat.addBothTo(17, M, M, M); + SecP521R1Field.reduce23(M); + + int[] S = Y1Squared; + SecP521R1Field.multiply(Y1Squared, X1.x, S); + Nat.shiftUpBits(17, S, 2, 0); + SecP521R1Field.reduce23(S); + + Nat.shiftUpBits(17, T, 3, 0, t1); + SecP521R1Field.reduce23(t1); + + SecP521R1FieldElement X3 = new SecP521R1FieldElement(T); + SecP521R1Field.square(M, X3.x); + SecP521R1Field.subtract(X3.x, S, X3.x); + SecP521R1Field.subtract(X3.x, S, X3.x); + + SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S); + SecP521R1Field.subtract(S, X3.x, Y3.x); + SecP521R1Field.multiply(Y3.x, M, Y3.x); + SecP521R1Field.subtract(Y3.x, t1, Y3.x); + + SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M); + SecP521R1Field.twice(Y1.x, Z3.x); + if (!Z1IsOne) + { + SecP521R1Field.multiply(Z3.x, Z1.x, Z3.x); + } + + return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, this.withCompression); + } + + public ECPoint twicePlus(ECPoint b) + { + if (this == b) + { + return threeTimes(); + } + if (this.isInfinity()) + { + return b; + } + if (b.isInfinity()) + { + return twice(); + } + + ECFieldElement Y1 = this.y; + if (Y1.isZero()) + { + return b; + } + + return twice().add(b); + } + + public ECPoint threeTimes() + { + if (this.isInfinity() || this.y.isZero()) + { + return this; + } + + // NOTE: Be careful about recursions between twicePlus and threeTimes + return twice().add(this); + } + + protected ECFieldElement two(ECFieldElement x) + { + return x.add(x); + } + + protected ECFieldElement three(ECFieldElement x) + { + return two(x).add(x); + } + + protected ECFieldElement four(ECFieldElement x) + { + return two(two(x)); + } + + protected ECFieldElement eight(ECFieldElement x) + { + return four(two(x)); + } + + protected ECFieldElement doubleProductFromSquares(ECFieldElement a, ECFieldElement b, + ECFieldElement aSquared, ECFieldElement bSquared) + { + /* + * NOTE: If squaring in the field is faster than multiplication, then this is a quicker + * way to calculate 2.A.B, if A^2 and B^2 are already known. + */ + return a.add(b).square().subtract(aSquared).subtract(bSquared); + } + + public ECPoint negate() + { + if (this.isInfinity()) + { + return this; + } + + return new SecP521R1Point(curve, this.x, this.y.negate(), this.zs, this.withCompression); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java new file mode 100644 index 000000000..7396bf331 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/ECEndomorphism.java @@ -0,0 +1,10 @@ +package org.spongycastle.math.ec.endo; + +import org.spongycastle.math.ec.ECPointMap; + +public interface ECEndomorphism +{ + ECPointMap getPointMap(); + + boolean hasEfficientPointMap(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java new file mode 100644 index 000000000..9c251a1ea --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVEndomorphism.java @@ -0,0 +1,8 @@ +package org.spongycastle.math.ec.endo; + +import java.math.BigInteger; + +public interface GLVEndomorphism extends ECEndomorphism +{ + BigInteger[] decomposeScalar(BigInteger k); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java new file mode 100644 index 000000000..884cbf53f --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBEndomorphism.java @@ -0,0 +1,58 @@ +package org.spongycastle.math.ec.endo; + +import java.math.BigInteger; + +import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPointMap; +import org.spongycastle.math.ec.ScaleXPointMap; + +public class GLVTypeBEndomorphism implements GLVEndomorphism +{ + protected final ECCurve curve; + protected final GLVTypeBParameters parameters; + protected final ECPointMap pointMap; + + public GLVTypeBEndomorphism(ECCurve curve, GLVTypeBParameters parameters) + { + this.curve = curve; + this.parameters = parameters; + this.pointMap = new ScaleXPointMap(curve.fromBigInteger(parameters.getBeta())); + } + + public BigInteger[] decomposeScalar(BigInteger k) + { + int bits = parameters.getBits(); + BigInteger b1 = calculateB(k, parameters.getG1(), bits); + BigInteger b2 = calculateB(k, parameters.getG2(), bits); + + BigInteger[] v1 = parameters.getV1(), v2 = parameters.getV2(); + BigInteger a = k.subtract((b1.multiply(v1[0])).add(b2.multiply(v2[0]))); + BigInteger b = (b1.multiply(v1[1])).add(b2.multiply(v2[1])).negate(); + + return new BigInteger[]{ a, b }; + } + + public ECPointMap getPointMap() + { + return pointMap; + } + + public boolean hasEfficientPointMap() + { + return true; + } + + protected BigInteger calculateB(BigInteger k, BigInteger g, int t) + { + boolean negative = (g.signum() < 0); + BigInteger b = k.multiply(g.abs()); + boolean extra = b.testBit(t - 1); + b = b.shiftRight(t); + if (extra) + { + b = b.add(ECConstants.ONE); + } + return negative ? b.negate() : b; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java new file mode 100644 index 000000000..92dbfd0e8 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/endo/GLVTypeBParameters.java @@ -0,0 +1,59 @@ +package org.spongycastle.math.ec.endo; + +import java.math.BigInteger; + +public class GLVTypeBParameters +{ + protected final BigInteger beta; + protected final BigInteger lambda; + protected final BigInteger[] v1, v2; + protected final BigInteger g1, g2; + protected final int bits; + + public GLVTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2, BigInteger g1, + BigInteger g2, int bits) + { + this.beta = beta; + this.lambda = lambda; + this.v1 = v1; + this.v2 = v2; + this.g1 = g1; + this.g2 = g2; + this.bits = bits; + } + + public BigInteger getBeta() + { + return beta; + } + + public BigInteger getLambda() + { + return lambda; + } + + public BigInteger[] getV1() + { + return v1; + } + + public BigInteger[] getV2() + { + return v2; + } + + public BigInteger getG1() + { + return g1; + } + + public BigInteger getG2() + { + return g2; + } + + public int getBits() + { + return bits; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java new file mode 100644 index 000000000..32341d605 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/ec/tools/DiscoverEndomorphisms.java @@ -0,0 +1,373 @@ +package org.spongycastle.math.ec.tools; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.spongycastle.asn1.x9.ECNamedCurveTable; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.math.ec.ECAlgorithms; +import org.spongycastle.math.ec.ECConstants; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECFieldElement; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.util.BigIntegers; + +public class DiscoverEndomorphisms +{ + private static final int radix = 16; + + public static void main(String[] args) + { + if (args.length < 1) + { + System.err.println("Expected a list of curve names as arguments"); + return; + } + + for (int i = 0; i < args.length; ++i) + { + discoverEndomorphism(args[i]); + } + } + + private static void discoverEndomorphism(String curveName) + { + X9ECParameters x9 = ECNamedCurveTable.getByName(curveName); + if (x9 == null) + { + System.err.println("Unknown curve: " + curveName); + return; + } + + ECCurve c = x9.getCurve(); + if (ECAlgorithms.isFpCurve(c)) + { + BigInteger characteristic = c.getField().getCharacteristic(); + + if (c.getA().isZero() && characteristic.mod(ECConstants.THREE).equals(ECConstants.ONE)) + { + System.out.println("Curve '" + curveName + "' has a 'GLV Type B' endomorphism with these parameters: "); + printGLVTypeBParameters(x9); + } + } + } + + private static void printGLVTypeBParameters(X9ECParameters x9) + { + BigInteger n = x9.getN(); + BigInteger[] v1 = null; + BigInteger[] v2 = null; + + // x^2 + x + 1 = 0 mod n + BigInteger lambda = solveQuadraticEquation(n, ECConstants.ONE, ECConstants.ONE); + + BigInteger[] rt = extEuclidGLV(n, lambda); + v1 = new BigInteger[]{ rt[2], rt[3].negate() }; + v2 = chooseShortest(new BigInteger[]{ rt[0], rt[1].negate() }, new BigInteger[]{ rt[4], rt[5].negate() }); + + /* + * If elements of v2 are not bounded by sqrt(n), then if r1/t1 are relatively prime there + * _may_ yet be a GLV generator, so search for it. See + * "Integer Decomposition for Fast Scalar Multiplication on Elliptic Curves", D. Kim, S. Lim + * (SAC 2002) + */ + if (!isVectorBoundedBySqrt(v2, n) && areRelativelyPrime(v1[0], v1[1])) + { + BigInteger r = v1[0], t = v1[1], s = r.add(t.multiply(lambda)).divide(n); + + BigInteger[] vw = extEuclidBezout(new BigInteger[]{ s.abs(), t.abs() }); + BigInteger v = vw[0], w = vw[1]; + + if (s.signum() < 0) + { + v = v.negate(); + } + if (t.signum() > 0) + { + w = w.negate(); + } + + BigInteger check = s.multiply(v).subtract(t.multiply(w)); + if (!check.equals(ECConstants.ONE)) + { + throw new IllegalStateException(); + } + + BigInteger x = w.multiply(n).subtract(v.multiply(lambda)); + + BigInteger base1 = v.negate(); + BigInteger base2 = x.negate(); + + /* + * We calculate the range(s) conservatively large to avoid messy rounding issues, so + * there may be spurious candidate generators, but we won't miss any. + */ + BigInteger sqrtN = isqrt(n.subtract(ECConstants.ONE)).add(ECConstants.ONE); + + BigInteger[] I1 = calculateRange(base1, sqrtN, t); + BigInteger[] I2 = calculateRange(base2, sqrtN, r); + + BigInteger[] range = intersect(I1, I2); + if (range != null) + { + for (BigInteger alpha = range[0]; alpha.compareTo(range[1]) <= 0; alpha = alpha.add(ECConstants.ONE)) + { + BigInteger[] candidate = new BigInteger[]{ x.add(alpha.multiply(r)), v.add(alpha.multiply(t)) }; + if (isShorter(candidate, v2)) + { + v2 = candidate; + } + } + } + } + + /* + * 'Beta' is a field element of order 3. There are only two such values besides 1; determine which of them + * corresponds to our choice for 'Lambda'. + */ + ECFieldElement beta; + { + ECPoint G = x9.getG().normalize(); + ECPoint mapG = G.multiply(lambda).normalize(); + if (!G.getYCoord().equals(mapG.getYCoord())) + { + throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly"); + } + + BigInteger q = x9.getCurve().getField().getCharacteristic(); + BigInteger e = q.divide(ECConstants.THREE); + + SecureRandom random = new SecureRandom(); + BigInteger b; + do + { + BigInteger r = BigIntegers.createRandomInRange(ECConstants.TWO, q.subtract(ECConstants.TWO), random); + b = r.modPow(e, q); + } + while (b.equals(ECConstants.ONE)); + + beta = x9.getCurve().fromBigInteger(ECConstants.TWO.modPow(e, q)); + + if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord())) + { + beta = beta.square(); + if (!G.getXCoord().multiply(beta).equals(mapG.getXCoord())) + { + throw new IllegalStateException("Derivation of GLV Type B parameters failed unexpectedly"); + } + } + } + + /* + * These parameters are used to avoid division when decomposing the scalar in a GLV point multiplication + */ + BigInteger d = (v1[0].multiply(v2[1])).subtract(v1[1].multiply(v2[0])); + + int bits = n.bitLength() + 16 - (n.bitLength() & 7); + BigInteger g1 = roundQuotient(v2[1].shiftLeft(bits), d); + BigInteger g2 = roundQuotient(v1[1].shiftLeft(bits), d).negate(); + + printProperty("Beta", beta.toBigInteger().toString(radix)); + printProperty("Lambda", lambda.toString(radix)); + printProperty("v1", "{ " + v1[0].toString(radix) + ", " + v1[1].toString(radix) + " }"); + printProperty("v2", "{ " + v2[0].toString(radix) + ", " + v2[1].toString(radix) + " }"); + printProperty("(OPT) g1", g1.toString(radix)); + printProperty("(OPT) g2", g2.toString(radix)); + printProperty("(OPT) bits", Integer.toString(bits)); + } + + private static void printProperty(String name, Object value) + { + StringBuffer sb = new StringBuffer(" "); + sb.append(name); + while (sb.length() < 20) + { + sb.append(' '); + } + sb.append("= "); + sb.append(value.toString()); + System.out.println(sb.toString()); + } + + private static boolean areRelativelyPrime(BigInteger a, BigInteger b) + { + return a.gcd(b).equals(ECConstants.ONE); + } + + private static BigInteger[] calculateRange(BigInteger mid, BigInteger off, BigInteger div) + { + BigInteger i1 = mid.subtract(off).divide(div); + BigInteger i2 = mid.add(off).divide(div); + return order(i1, i2); + } + + private static BigInteger[] extEuclidBezout(BigInteger[] ab) + { + boolean swap = ab[0].compareTo(ab[1]) < 0; + if (swap) + { + swap(ab); + } + + BigInteger r0 = ab[0], r1 = ab[1]; + BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO; + BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE; + + while (r1.compareTo(ECConstants.ONE) > 0) + { + BigInteger[] qr = r0.divideAndRemainder(r1); + BigInteger q = qr[0], r2 = qr[1]; + + BigInteger s2 = s0.subtract(q.multiply(s1)); + BigInteger t2 = t0.subtract(q.multiply(t1)); + + r0 = r1; + r1 = r2; + s0 = s1; + s1 = s2; + t0 = t1; + t1 = t2; + } + + if (r1.signum() <= 0) + { + throw new IllegalStateException(); + } + + BigInteger[] st = new BigInteger[]{ s1, t1 }; + if (swap) + { + swap(st); + } + return st; + } + + private static BigInteger[] extEuclidGLV(BigInteger n, BigInteger lambda) + { + BigInteger r0 = n, r1 = lambda; + // BigInteger s0 = ECConstants.ONE, s1 = ECConstants.ZERO; + BigInteger t0 = ECConstants.ZERO, t1 = ECConstants.ONE; + + for (;;) + { + BigInteger[] qr = r0.divideAndRemainder(r1); + BigInteger q = qr[0], r2 = qr[1]; + + // BigInteger s2 = s0.subtract(q.multiply(s1)); + BigInteger t2 = t0.subtract(q.multiply(t1)); + + if (isLessThanSqrt(r1, n)) + { + return new BigInteger[]{ r0, t0, r1, t1, r2, t2 }; + } + + r0 = r1; + r1 = r2; + // s0 = s1; + // s1 = s2; + t0 = t1; + t1 = t2; + } + } + + private static BigInteger[] chooseShortest(BigInteger[] u, BigInteger[] v) + { + return isShorter(u, v) ? u : v; + } + + private static BigInteger[] intersect(BigInteger[] ab, BigInteger[] cd) + { + BigInteger min = ab[0].max(cd[0]); + BigInteger max = ab[1].min(cd[1]); + if (min.compareTo(max) > 0) + { + return null; + } + return new BigInteger[]{ min, max }; + } + + private static boolean isLessThanSqrt(BigInteger a, BigInteger b) + { + a = a.abs(); + b = b.abs(); + int target = b.bitLength(), maxBits = a.bitLength() * 2, minBits = maxBits - 1; + return minBits <= target && (maxBits < target || a.multiply(a).compareTo(b) < 0); + } + + private static boolean isShorter(BigInteger[] u, BigInteger[] v) + { + BigInteger u1 = u[0].abs(), u2 = u[1].abs(), v1 = v[0].abs(), v2 = v[1].abs(); + + // TODO Check whether "shorter" just means by rectangle norm: + // return u1.max(u2).compareTo(v1.max(v2)) < 0; + + boolean c1 = u1.compareTo(v1) < 0, c2 = u2.compareTo(v2) < 0; + if (c1 == c2) + { + return c1; + } + + BigInteger du = u1.multiply(u1).add(u2.multiply(u2)); + BigInteger dv = v1.multiply(v1).add(v2.multiply(v2)); + + return du.compareTo(dv) < 0; + } + + private static boolean isVectorBoundedBySqrt(BigInteger[] v, BigInteger n) + { + BigInteger max = v[0].abs().max(v[1].abs()); + return isLessThanSqrt(max, n); + } + + private static BigInteger[] order(BigInteger a, BigInteger b) + { + if (a.compareTo(b) <= 0) + { + return new BigInteger[]{ a, b }; + } + return new BigInteger[]{ b, a }; + } + + private static BigInteger roundQuotient(BigInteger x, BigInteger y) + { + boolean negative = (x.signum() != y.signum()); + x = x.abs(); + y = y.abs(); + BigInteger result = x.add(y.shiftRight(1)).divide(y); + return negative ? result.negate() : result; + } + + private static BigInteger solveQuadraticEquation(BigInteger n, BigInteger r, BigInteger s) + { + BigInteger det = r.multiply(r).subtract(s.shiftLeft(2)).mod(n); + + BigInteger root = new ECFieldElement.Fp(n, det).sqrt().toBigInteger(); + if (!root.testBit(0)) + { + root = n.subtract(root); + } + + return root.shiftRight(1); // NOTE: implicit -1 of the low-bit + } + + private static BigInteger isqrt(BigInteger x) + { + BigInteger g0 = x.shiftRight(x.bitLength() / 2); + for (;;) + { + BigInteger g1 = g0.add(x.divide(g0)).shiftRight(1); + if (g1.equals(g0)) + { + return g1; + } + g0 = g1; + } + } + + private static void swap(BigInteger[] ab) + { + BigInteger tmp = ab[0]; + ab[0] = ab[1]; + ab[1] = tmp; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/ExtensionField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/ExtensionField.java new file mode 100644 index 000000000..d32fda587 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/ExtensionField.java @@ -0,0 +1,8 @@ +package org.spongycastle.math.field; + +public interface ExtensionField extends FiniteField +{ + FiniteField getSubfield(); + + int getDegree(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteField.java new file mode 100644 index 000000000..25801c315 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteField.java @@ -0,0 +1,10 @@ +package org.spongycastle.math.field; + +import java.math.BigInteger; + +public interface FiniteField +{ + BigInteger getCharacteristic(); + + int getDimension(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteFields.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteFields.java new file mode 100644 index 000000000..602d32e63 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/FiniteFields.java @@ -0,0 +1,53 @@ +package org.spongycastle.math.field; + +import java.math.BigInteger; + +public abstract class FiniteFields +{ + static final FiniteField GF_2 = new PrimeField(BigInteger.valueOf(2)); + static final FiniteField GF_3 = new PrimeField(BigInteger.valueOf(3)); + + public static PolynomialExtensionField getBinaryExtensionField(int[] exponents) + { + if (exponents[0] != 0) + { + throw new IllegalArgumentException("Irreducible polynomials in GF(2) must have constant term"); + } + for (int i = 1; i < exponents.length; ++i) + { + if (exponents[i] <= exponents[i - 1]) + { + throw new IllegalArgumentException("Polynomial exponents must be montonically increasing"); + } + } + + return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents)); + } + +// public static PolynomialExtensionField getTernaryExtensionField(Term[] terms) +// { +// return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms)); +// } + + public static FiniteField getPrimeField(BigInteger characteristic) + { + int bitLength = characteristic.bitLength(); + if (characteristic.signum() <= 0 || bitLength < 2) + { + throw new IllegalArgumentException("'characteristic' must be >= 2"); + } + + if (bitLength < 3) + { + switch (characteristic.intValue()) + { + case 2: + return GF_2; + case 3: + return GF_3; + } + } + + return new PrimeField(characteristic); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java new file mode 100644 index 000000000..a8e900c76 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GF2Polynomial.java @@ -0,0 +1,42 @@ +package org.spongycastle.math.field; + +import org.spongycastle.util.Arrays; + +class GF2Polynomial implements Polynomial +{ + protected final int[] exponents; + + GF2Polynomial(int[] exponents) + { + this.exponents = Arrays.clone(exponents); + } + + public int getDegree() + { + return exponents[exponents.length - 1]; + } + + public int[] getExponentsPresent() + { + return Arrays.clone(exponents); + } + + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof GF2Polynomial)) + { + return false; + } + GF2Polynomial other = (GF2Polynomial)obj; + return Arrays.areEqual(exponents, other.exponents); + } + + public int hashCode() + { + return Arrays.hashCode(exponents); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java new file mode 100644 index 000000000..677cff961 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/GenericPolynomialExtensionField.java @@ -0,0 +1,62 @@ +package org.spongycastle.math.field; + +import java.math.BigInteger; + +import org.spongycastle.util.Integers; + +class GenericPolynomialExtensionField implements PolynomialExtensionField +{ + protected final FiniteField subfield; + protected final Polynomial minimalPolynomial; + + GenericPolynomialExtensionField(FiniteField subfield, Polynomial polynomial) + { + this.subfield = subfield; + this.minimalPolynomial = polynomial; + } + + public BigInteger getCharacteristic() + { + return subfield.getCharacteristic(); + } + + public int getDimension() + { + return subfield.getDimension() * minimalPolynomial.getDegree(); + } + + public FiniteField getSubfield() + { + return subfield; + } + + public int getDegree() + { + return minimalPolynomial.getDegree(); + } + + public Polynomial getMinimalPolynomial() + { + return minimalPolynomial; + } + + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof GenericPolynomialExtensionField)) + { + return false; + } + GenericPolynomialExtensionField other = (GenericPolynomialExtensionField)obj; + return subfield.equals(other.subfield) && minimalPolynomial.equals(other.minimalPolynomial); + } + + public int hashCode() + { + return subfield.hashCode() + ^ Integers.rotateLeft(minimalPolynomial.hashCode(), 16); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/Polynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/Polynomial.java new file mode 100644 index 000000000..b0724cb5c --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/Polynomial.java @@ -0,0 +1,12 @@ +package org.spongycastle.math.field; + +public interface Polynomial +{ + int getDegree(); + +// BigInteger[] getCoefficients(); + + int[] getExponentsPresent(); + +// Term[] getNonZeroTerms(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java new file mode 100644 index 000000000..35eb98ead --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PolynomialExtensionField.java @@ -0,0 +1,6 @@ +package org.spongycastle.math.field; + +public interface PolynomialExtensionField extends ExtensionField +{ + Polynomial getMinimalPolynomial(); +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PrimeField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PrimeField.java new file mode 100644 index 000000000..38c313a73 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/field/PrimeField.java @@ -0,0 +1,42 @@ +package org.spongycastle.math.field; + +import java.math.BigInteger; + +class PrimeField implements FiniteField +{ + protected final BigInteger characteristic; + + PrimeField(BigInteger characteristic) + { + this.characteristic = characteristic; + } + + public BigInteger getCharacteristic() + { + return characteristic; + } + + public int getDimension() + { + return 1; + } + + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof PrimeField)) + { + return false; + } + PrimeField other = (PrimeField)obj; + return characteristic.equals(other.characteristic); + } + + public int hashCode() + { + return characteristic.hashCode(); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mod.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mod.java new file mode 100644 index 000000000..6bb8d7480 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mod.java @@ -0,0 +1,199 @@ +package org.spongycastle.math.raw; + +import java.util.Random; + +import org.spongycastle.util.Pack; + +public abstract class Mod +{ + public static int inverse32(int d) + { +// int x = d + (((d + 1) & 4) << 1); // d.x == 1 mod 2**4 + int x = d; // d.x == 1 mod 2**3 + x *= 2 - d * x; // d.x == 1 mod 2**6 + x *= 2 - d * x; // d.x == 1 mod 2**12 + x *= 2 - d * x; // d.x == 1 mod 2**24 + x *= 2 - d * x; // d.x == 1 mod 2**48 +// assert d * x == 1; + return x; + } + + public static void invert(int[] p, int[] x, int[] z) + { + int len = p.length; + if (Nat.isZero(len, x)) + { + throw new IllegalArgumentException("'x' cannot be 0"); + } + if (Nat.isOne(len, x)) + { + System.arraycopy(x, 0, z, 0, len); + return; + } + + int[] u = Nat.copy(len, x); + int[] a = Nat.create(len); + a[0] = 1; + int ac = 0; + + if ((u[0] & 1) == 0) + { + ac = inversionStep(p, u, len, a, ac); + } + if (Nat.isOne(len, u)) + { + inversionResult(p, ac, a, z); + return; + } + + int[] v = Nat.copy(len, p); + int[] b = Nat.create(len); + int bc = 0; + + int uvLen = len; + + for (;;) + { + while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0) + { + --uvLen; + } + + if (Nat.gte(uvLen, u, v)) + { + Nat.subFrom(uvLen, v, u); +// assert (u[0] & 1) == 0; + ac += Nat.subFrom(len, b, a) - bc; + ac = inversionStep(p, u, uvLen, a, ac); + if (Nat.isOne(uvLen, u)) + { + inversionResult(p, ac, a, z); + return; + } + } + else + { + Nat.subFrom(uvLen, u, v); +// assert (v[0] & 1) == 0; + bc += Nat.subFrom(len, a, b) - ac; + bc = inversionStep(p, v, uvLen, b, bc); + if (Nat.isOne(uvLen, v)) + { + inversionResult(p, bc, b, z); + return; + } + } + } + } + + public static int[] random(int[] p) + { + int len = p.length; + Random rand = new Random(); + int[] s = Nat.create(len); + + int m = p[len - 1]; + m |= m >>> 1; + m |= m >>> 2; + m |= m >>> 4; + m |= m >>> 8; + m |= m >>> 16; + + do + { + for (int i = 0; i != len; i++) + { + s[i] = rand.nextInt(); + } + s[len - 1] &= m; + } + while (Nat.gte(len, s, p)); + + return s; + } + + public static void add(int[] p, int[] x, int[] y, int[] z) + { + int len = p.length; + int c = Nat.add(len, x, y, z); + if (c != 0) + { + Nat.subFrom(len, p, z); + } + } + + public static void subtract(int[] p, int[] x, int[] y, int[] z) + { + int len = p.length; + int c = Nat.sub(len, x, y, z); + if (c != 0) + { + Nat.addTo(len, p, z); + } + } + + private static void inversionResult(int[] p, int ac, int[] a, int[] z) + { + if (ac < 0) + { + Nat.add(p.length, a, p, z); + } + else + { + System.arraycopy(a, 0, z, 0, p.length); + } + } + + private static int inversionStep(int[] p, int[] u, int uLen, int[] x, int xc) + { + int len = p.length; + int count = 0; + while (u[0] == 0) + { + Nat.shiftDownWord(uLen, u, 0); + count += 32; + } + + { + int zeroes = getTrailingZeroes(u[0]); + if (zeroes > 0) + { + Nat.shiftDownBits(uLen, u, zeroes, 0); + count += zeroes; + } + } + + for (int i = 0; i < count; ++i) + { + if ((x[0] & 1) != 0) + { + if (xc < 0) + { + xc += Nat.addTo(len, p, x); + } + else + { + xc += Nat.subFrom(len, p, x); + } + } + +// assert xc == 0 || xc == 1; + Nat.shiftDownBit(len, x, xc); + } + + return xc; + } + + private static int getTrailingZeroes(int x) + { +// assert x != 0; + + int count = 0; + while ((x & 1) == 0) + { + x >>>= 1; + ++count; + } + return count; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mont256.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mont256.java new file mode 100644 index 000000000..b90dcc5a1 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Mont256.java @@ -0,0 +1,152 @@ +package org.spongycastle.math.raw; + +public abstract class Mont256 +{ + private static final long M = 0xFFFFFFFFL; + + public static int inverse32(int x) + { + // assert (x & 1) == 1; + int z = x; // x.z == 1 mod 2**3 + z *= 2 - x * z; // x.z == 1 mod 2**6 + z *= 2 - x * z; // x.z == 1 mod 2**12 + z *= 2 - x * z; // x.z == 1 mod 2**24 + z *= 2 - x * z; // x.z == 1 mod 2**48 + // assert x * z == 1; + return z; + } + + public static void multAdd(int[] x, int[] y, int[] z, int[] m, int mInv32) + { + int z_8 = 0; + long y_0 = y[0] & M; + + for (int i = 0; i < 8; ++i) + { + long z_0 = z[0] & M; + long x_i = x[i] & M; + + long prod1 = x_i * y_0; + long carry = (prod1 & M) + z_0; + + long t = ((int)carry * mInv32) & M; + + long prod2 = t * (m[0] & M); + carry += (prod2 & M); + // assert (int)carry == 0; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + + for (int j = 1; j < 8; ++j) + { + prod1 = x_i * (y[j] & M); + prod2 = t * (m[j] & M); + + carry += (prod1 & M) + (prod2 & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + } + + carry += (z_8 & M); + z[7] = (int)carry; + z_8 = (int)(carry >>> 32); + } + + if (z_8 != 0 || Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void multAddXF(int[] x, int[] y, int[] z, int[] m) + { + // assert m[0] == M; + + int z_8 = 0; + long y_0 = y[0] & M; + + for (int i = 0; i < 8; ++i) + { + long x_i = x[i] & M; + + long carry = x_i * y_0 + (z[0] & M); + long t = carry & M; + carry = (carry >>> 32) + t; + + for (int j = 1; j < 8; ++j) + { + long prod1 = x_i * (y[j] & M); + long prod2 = t * (m[j] & M); + + carry += (prod1 & M) + (prod2 & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + } + + carry += (z_8 & M); + z[7] = (int)carry; + z_8 = (int)(carry >>> 32); + } + + if (z_8 != 0 || Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void reduce(int[] z, int[] m, int mInv32) + { + for (int i = 0; i < 8; ++i) + { + int z_0 = z[0]; + + long t = (z_0 * mInv32) & M; + + long carry = t * (m[0] & M) + (z_0 & M); + // assert (int)carry == 0; + carry >>>= 32; + + for (int j = 1; j < 8; ++j) + { + carry += t * (m[j] & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry >>>= 32; + } + + z[7] = (int)carry; + // assert carry >>> 32 == 0; + } + + if (Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void reduceXF(int[] z, int[] m) + { + // assert m[0] == M; + + for (int i = 0; i < 8; ++i) + { + int z_0 = z[0]; + + long t = z_0 & M; + long carry = t; + + for (int j = 1; j < 8; ++j) + { + carry += t * (m[j] & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry >>>= 32; + } + + z[7] = (int)carry; + // assert carry >>> 32 == 0; + } + + if (Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat.java new file mode 100644 index 000000000..149096739 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat.java @@ -0,0 +1,1038 @@ +package org.spongycastle.math.raw; + +import java.math.BigInteger; + +import org.spongycastle.util.Pack; + +public abstract class Nat +{ + private static final long M = 0xFFFFFFFFL; + + public static int add(int len, int[] x, int[] y, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[i] & M) + (y[i] & M); + z[i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int add33At(int len, int x, int[] z, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zPos + 0] & M) + (x & M); + z[zPos + 0] = (int)c; + c >>>= 32; + c += (z[zPos + 1] & M) + 1L; + z[zPos + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zPos + 2); + } + + public static int add33At(int len, int x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zOff + zPos] & M) + (x & M); + z[zOff + zPos] = (int)c; + c >>>= 32; + c += (z[zOff + zPos + 1] & M) + 1L; + z[zOff + zPos + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2); + } + + public static int add33To(int len, int x, int[] z) + { + long c = (z[0] & M) + (x & M); + z[0] = (int)c; + c >>>= 32; + c += (z[1] & M) + 1L; + z[1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, 2); + } + + public static int add33To(int len, int x, int[] z, int zOff) + { + long c = (z[zOff + 0] & M) + (x & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (z[zOff + 1] & M) + 1L; + z[zOff + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, 2); + } + + public static int addBothTo(int len, int[] x, int[] y, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[i] & M) + (y[i] & M) + (z[i] & M); + z[i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int addBothTo(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[xOff + i] & M) + (y[yOff + i] & M) + (z[zOff + i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int addDWordAt(int len, long x, int[] z, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zPos + 0] & M) + (x & M); + z[zPos + 0] = (int)c; + c >>>= 32; + c += (z[zPos + 1] & M) + (x >>> 32); + z[zPos + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zPos + 2); + } + + public static int addDWordAt(int len, long x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zOff + zPos] & M) + (x & M); + z[zOff + zPos] = (int)c; + c >>>= 32; + c += (z[zOff + zPos + 1] & M) + (x >>> 32); + z[zOff + zPos + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, zPos + 2); + } + + public static int addDWordTo(int len, long x, int[] z) + { + long c = (z[0] & M) + (x & M); + z[0] = (int)c; + c >>>= 32; + c += (z[1] & M) + (x >>> 32); + z[1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, 2); + } + + public static int addDWordTo(int len, long x, int[] z, int zOff) + { + long c = (z[zOff + 0] & M) + (x & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (z[zOff + 1] & M) + (x >>> 32); + z[zOff + 1] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, 2); + } + + public static int addTo(int len, int[] x, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[i] & M) + (z[i] & M); + z[i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int addTo(int len, int[] x, int xOff, int[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[xOff + i] & M) + (z[zOff + i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + return (int)c; + } + + public static int addWordAt(int len, int x, int[] z, int zPos) + { + // assert zPos <= (len - 1); + long c = (x & M) + (z[zPos] & M); + z[zPos] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zPos + 1); + } + + public static int addWordAt(int len, int x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 1); + long c = (x & M) + (z[zOff + zPos] & M); + z[zOff + zPos] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, zPos + 1); + } + + public static int addWordTo(int len, int x, int[] z) + { + long c = (x & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, 1); + } + + public static int addWordTo(int len, int x, int[] z, int zOff) + { + long c = (x & M) + (z[zOff] & M); + z[zOff] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zOff, 1); + } + + public static int[] copy(int len, int[] x) + { + int[] z = new int[len]; + System.arraycopy(x, 0, z, 0, len); + return z; + } + + public static void copy(int len, int[] x, int[] z) + { + System.arraycopy(x, 0, z, 0, len); + } + + public static int[] create(int len) + { + return new int[len]; + } + + public static int dec(int len, int[] z) + { + for (int i = 0; i < len; ++i) + { + if (--z[i] != -1) + { + return 0; + } + } + return -1; + } + + public static int dec(int len, int[] x, int[] z) + { + int i = 0; + while (i < len) + { + int c = x[i] - 1; + z[i] = c; + ++i; + if (c != -1) + { + while (i < len) + { + z[i] = x[i]; + ++i; + } + return 0; + } + } + return -1; + } + + public static int decAt(int len, int[] z, int zPos) + { + // assert zPos <= len; + for (int i = zPos; i < len; ++i) + { + if (--z[i] != -1) + { + return 0; + } + } + return -1; + } + + public static int decAt(int len, int[] z, int zOff, int zPos) + { + // assert zPos <= len; + for (int i = zPos; i < len; ++i) + { + if (--z[zOff + i] != -1) + { + return 0; + } + } + return -1; + } + + public static boolean eq(int len, int[] x, int[] y) + { + for (int i = len - 1; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static int[] fromBigInteger(int bits, BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > bits) + { + throw new IllegalArgumentException(); + } + + int len = (bits + 31) >> 5; + int[] z = create(len); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.intValue(); + x = x.shiftRight(32); + } + return z; + } + + public static int getBit(int[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= x.length) + { + return 0; + } + int b = bit & 31; + return (x[w] >>> b) & 1; + } + + public static boolean gte(int len, int[] x, int[] y) + { + for (int i = len - 1; i >= 0; --i) + { + int x_i = x[i] ^ Integer.MIN_VALUE; + int y_i = y[i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static int inc(int len, int[] z) + { + for (int i = 0; i < len; ++i) + { + if (++z[i] != 0) + { + return 0; + } + } + return 1; + } + + public static int inc(int len, int[] x, int[] z) + { + int i = 0; + while (i < len) + { + int c = x[i] + 1; + z[i] = c; + ++i; + if (c != 0) + { + while (i < len) + { + z[i] = x[i]; + ++i; + } + return 0; + } + } + return 1; + } + + public static int incAt(int len, int[] z, int zPos) + { + // assert zPos <= len; + for (int i = zPos; i < len; ++i) + { + if (++z[i] != 0) + { + return 0; + } + } + return 1; + } + + public static int incAt(int len, int[] z, int zOff, int zPos) + { + // assert zPos <= len; + for (int i = zPos; i < len; ++i) + { + if (++z[zOff + i] != 0) + { + return 0; + } + } + return 1; + } + + public static boolean isOne(int len, int[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < len; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static boolean isZero(int len, int[] x) + { + for (int i = 0; i < len; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void mul(int len, int[] x, int[] y, int[] zz) + { + zz[len] = mulWord(len, x[0], y, zz); + + for (int i = 1; i < len; ++i) + { + zz[i + len] = mulWordAddTo(len, x[i], y, 0, zz, i); + } + } + + public static void mul(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + zz[zzOff + len] = mulWord(len, x[xOff], y, yOff, zz, zzOff); + + for (int i = 1; i < len; ++i) + { + zz[zzOff + i + len] = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i); + } + } + + public static int mulAddTo(int len, int[] x, int[] y, int[] zz) + { + long zc = 0; + for (int i = 0; i < len; ++i) + { + long c = mulWordAddTo(len, x[i], y, 0, zz, i) & M; + c += zc + (zz[i + len] & M); + zz[i + len] = (int)c; + zc = c >>> 32; + } + return (int)zc; + } + + public static int mulAddTo(int len, int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long zc = 0; + for (int i = 0; i < len; ++i) + { + long c = mulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff) & M; + c += zc + (zz[zzOff + len] & M); + zz[zzOff + len] = (int)c; + zc = c >>> 32; + ++zzOff; + } + return (int)zc; + } + + public static int mul31BothAdd(int len, int a, int[] x, int b, int[] y, int[] z, int zOff) + { + long c = 0, aVal = a & M, bVal = b & M; + int i = 0; + do + { + c += aVal * (x[i] & M) + bVal * (y[i] & M) + (z[zOff + i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < len); + return (int)c; + } + + public static int mulWord(int len, int x, int[] y, int[] z) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[i] & M); + z[i] = (int)c; + c >>>= 32; + } + while (++i < len); + return (int)c; + } + + public static int mulWord(int len, int x, int[] y, int yOff, int[] z, int zOff) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[yOff + i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < len); + return (int)c; + } + + public static int mulWordAddTo(int len, int x, int[] y, int yOff, int[] z, int zOff) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[yOff + i] & M) + (z[zOff + i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < len); + return (int)c; + } + + public static int mulWordDwordAddAt(int len, int x, long y, int[] z, int zPos) + { + // assert zPos <= (len - 3); + long c = 0, xVal = x & M; + c += xVal * (y & M) + (z[zPos + 0] & M); + z[zPos + 0] = (int)c; + c >>>= 32; + c += xVal * (y >>> 32) + (z[zPos + 1] & M); + z[zPos + 1] = (int)c; + c >>>= 32; + c += (z[zPos + 2] & M); + z[zPos + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : incAt(len, z, zPos + 3); + } + + public static int shiftDownBit(int len, int[] z, int c) + { + int i = len; + while (--i >= 0) + { + int next = z[i]; + z[i] = (next >>> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static int shiftDownBit(int len, int[] z, int zOff, int c) + { + int i = len; + while (--i >= 0) + { + int next = z[zOff + i]; + z[zOff + i] = (next >>> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static int shiftDownBit(int len, int[] x, int c, int[] z) + { + int i = len; + while (--i >= 0) + { + int next = x[i]; + z[i] = (next >>> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static int shiftDownBit(int len, int[] x, int xOff, int c, int[] z, int zOff) + { + int i = len; + while (--i >= 0) + { + int next = x[xOff + i]; + z[zOff + i] = (next >>> 1) | (c << 31); + c = next; + } + return c << 31; + } + + public static int shiftDownBits(int len, int[] z, int bits, int c) + { +// assert bits > 0 && bits < 32; + int i = len; + while (--i >= 0) + { + int next = z[i]; + z[i] = (next >>> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static int shiftDownBits(int len, int[] z, int zOff, int bits, int c) + { +// assert bits > 0 && bits < 32; + int i = len; + while (--i >= 0) + { + int next = z[zOff + i]; + z[zOff + i] = (next >>> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static int shiftDownBits(int len, int[] x, int bits, int c, int[] z) + { +// assert bits > 0 && bits < 32; + int i = len; + while (--i >= 0) + { + int next = x[i]; + z[i] = (next >>> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static int shiftDownBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff) + { +// assert bits > 0 && bits < 32; + int i = len; + while (--i >= 0) + { + int next = x[xOff + i]; + z[zOff + i] = (next >>> bits) | (c << -bits); + c = next; + } + return c << -bits; + } + + public static int shiftDownWord(int len, int[] z, int c) + { + int i = len; + while (--i >= 0) + { + int next = z[i]; + z[i] = c; + c = next; + } + return c; + } + + public static int shiftUpBit(int len, int[] z, int c) + { + for (int i = 0; i < len; ++i) + { + int next = z[i]; + z[i] = (next << 1) | (c >>> 31); + c = next; + } + return c >>> 31; + } + + public static int shiftUpBit(int len, int[] z, int zOff, int c) + { + for (int i = 0; i < len; ++i) + { + int next = z[zOff + i]; + z[zOff + i] = (next << 1) | (c >>> 31); + c = next; + } + return c >>> 31; + } + + public static int shiftUpBit(int len, int[] x, int c, int[] z) + { + for (int i = 0; i < len; ++i) + { + int next = x[i]; + z[i] = (next << 1) | (c >>> 31); + c = next; + } + return c >>> 31; + } + + public static int shiftUpBit(int len, int[] x, int xOff, int c, int[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + int next = x[xOff + i]; + z[zOff + i] = (next << 1) | (c >>> 31); + c = next; + } + return c >>> 31; + } + + public static int shiftUpBits(int len, int[] z, int bits, int c) + { +// assert bits > 0 && bits < 32; + for (int i = 0; i < len; ++i) + { + int next = z[i]; + z[i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + + public static int shiftUpBits(int len, int[] z, int zOff, int bits, int c) + { +// assert bits > 0 && bits < 32; + for (int i = 0; i < len; ++i) + { + int next = z[zOff + i]; + z[zOff + i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + + public static int shiftUpBits(int len, int[] x, int bits, int c, int[] z) + { +// assert bits > 0 && bits < 32; + for (int i = 0; i < len; ++i) + { + int next = x[i]; + z[i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + + public static int shiftUpBits(int len, int[] x, int xOff, int bits, int c, int[] z, int zOff) + { +// assert bits > 0 && bits < 32; + for (int i = 0; i < len; ++i) + { + int next = x[xOff + i]; + z[zOff + i] = (next << bits) | (c >>> -bits); + c = next; + } + return c >>> -bits; + } + + public static void square(int len, int[] x, int[] zz) + { + int extLen = len << 1; + int c = 0; + int j = len, k = extLen; + do + { + long xVal = (x[--j] & M); + long p = xVal * xVal; + zz[--k] = (c << 31) | (int)(p >>> 33); + zz[--k] = (int)(p >>> 1); + c = (int)p; + } + while (j > 0); + + for (int i = 1; i < len; ++i) + { + c = squareWordAdd(x, i, zz); + addWordAt(extLen, c, zz, i << 1); + } + + shiftUpBit(extLen, zz, x[0] << 31); + } + + public static void square(int len, int[] x, int xOff, int[] zz, int zzOff) + { + int extLen = len << 1; + int c = 0; + int j = len, k = extLen; + do + { + long xVal = (x[xOff + --j] & M); + long p = xVal * xVal; + zz[zzOff + --k] = (c << 31) | (int)(p >>> 33); + zz[zzOff + --k] = (int)(p >>> 1); + c = (int)p; + } + while (j > 0); + + for (int i = 1; i < len; ++i) + { + c = squareWordAdd(x, xOff, i, zz, zzOff); + addWordAt(extLen, c, zz, zzOff, i << 1); + } + + shiftUpBit(extLen, zz, zzOff, x[xOff] << 31); + } + + public static int squareWordAdd(int[] x, int xPos, int[] z) + { + long c = 0, xVal = x[xPos] & M; + int i = 0; + do + { + c += xVal * (x[i] & M) + (z[xPos + i] & M); + z[xPos + i] = (int)c; + c >>>= 32; + } + while (++i < xPos); + return (int)c; + } + + public static int squareWordAdd(int[] x, int xOff, int xPos, int[] z, int zOff) + { + long c = 0, xVal = x[xOff + xPos] & M; + int i = 0; + do + { + c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M); + z[xPos + zOff] = (int)c; + c >>>= 32; + ++zOff; + } + while (++i < xPos); + return (int)c; + } + + public static int sub(int len, int[] x, int[] y, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[i] & M) - (y[i] & M); + z[i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int sub(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (x[xOff + i] & M) - (y[yOff + i] & M); + z[zOff + i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int sub33At(int len, int x, int[] z, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zPos + 0] & M) - (x & M); + z[zPos + 0] = (int)c; + c >>= 32; + c += (z[zPos + 1] & M) - 1; + z[zPos + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zPos + 2); + } + + public static int sub33At(int len, int x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zOff + zPos] & M) - (x & M); + z[zOff + zPos] = (int)c; + c >>= 32; + c += (z[zOff + zPos + 1] & M) - 1; + z[zOff + zPos + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2); + } + + public static int sub33From(int len, int x, int[] z) + { + long c = (z[0] & M) - (x & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - 1; + z[1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, 2); + } + + public static int sub33From(int len, int x, int[] z, int zOff) + { + long c = (z[zOff + 0] & M) - (x & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (z[zOff + 1] & M) - 1; + z[zOff + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, 2); + } + + public static int subBothFrom(int len, int[] x, int[] y, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (z[i] & M) - (x[i] & M) - (y[i] & M); + z[i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int subBothFrom(int len, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (z[zOff + i] & M) - (x[xOff + i] & M) - (y[yOff + i] & M); + z[zOff + i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int subDWordAt(int len, long x, int[] z, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zPos + 0] & M) - (x & M); + z[zPos + 0] = (int)c; + c >>= 32; + c += (z[zPos + 1] & M) - (x >>> 32); + z[zPos + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zPos + 2); + } + + public static int subDWordAt(int len, long x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 2); + long c = (z[zOff + zPos] & M) - (x & M); + z[zOff + zPos] = (int)c; + c >>= 32; + c += (z[zOff + zPos + 1] & M) - (x >>> 32); + z[zOff + zPos + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, zPos + 2); + } + + public static int subDWordFrom(int len, long x, int[] z) + { + long c = (z[0] & M) - (x & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x >>> 32); + z[1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, 2); + } + + public static int subDWordFrom(int len, long x, int[] z, int zOff) + { + long c = (z[zOff + 0] & M) - (x & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (z[zOff + 1] & M) - (x >>> 32); + z[zOff + 1] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, 2); + } + + public static int subFrom(int len, int[] x, int[] z) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (z[i] & M) - (x[i] & M); + z[i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int subFrom(int len, int[] x, int xOff, int[] z, int zOff) + { + long c = 0; + for (int i = 0; i < len; ++i) + { + c += (z[zOff + i] & M) - (x[xOff + i] & M); + z[zOff + i] = (int)c; + c >>= 32; + } + return (int)c; + } + + public static int subWordAt(int len, int x, int[] z, int zPos) + { + // assert zPos <= (len - 1); + long c = (z[zPos] & M) - (x & M); + z[zPos] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zPos + 1); + } + + public static int subWordAt(int len, int x, int[] z, int zOff, int zPos) + { + // assert zPos <= (len - 1); + long c = (z[zOff + zPos] & M) - (x & M); + z[zOff + zPos] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, zPos + 1); + } + + public static int subWordFrom(int len, int x, int[] z) + { + long c = (z[0] & M) - (x & M); + z[0] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, 1); + } + + public static int subWordFrom(int len, int x, int[] z, int zOff) + { + long c = (z[zOff + 0] & M) - (x & M); + z[zOff + 0] = (int)c; + c >>= 32; + return c == 0 ? 0 : decAt(len, z, zOff, 1); + } + + public static BigInteger toBigInteger(int len, int[] x) + { + byte[] bs = new byte[len << 2]; + for (int i = 0; i < len; ++i) + { + int x_i = x[i]; + if (x_i != 0) + { + Pack.intToBigEndian(x_i, bs, (len - 1 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void zero(int len, int[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] = 0; + } + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat192.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat192.java new file mode 100644 index 000000000..0b71cfe84 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat192.java @@ -0,0 +1,968 @@ +package org.spongycastle.math.raw; + +import java.math.BigInteger; + +import org.spongycastle.util.Pack; + +public abstract class Nat192 +{ + private static final long M = 0xFFFFFFFFL; + + public static int add(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M); + z[5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addBothTo(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int[] z) + { + long c = 0; + c += (x[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn) + { + long c = cIn & M; + c += (x[xOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addToEachOther(int[] u, int uOff, int[] v, int vOff) + { + long c = 0; + c += (u[uOff + 0] & M) + (v[vOff + 0] & M); + u[uOff + 0] = (int)c; + v[vOff + 0] = (int)c; + c >>>= 32; + c += (u[uOff + 1] & M) + (v[vOff + 1] & M); + u[uOff + 1] = (int)c; + v[vOff + 1] = (int)c; + c >>>= 32; + c += (u[uOff + 2] & M) + (v[vOff + 2] & M); + u[uOff + 2] = (int)c; + v[vOff + 2] = (int)c; + c >>>= 32; + c += (u[uOff + 3] & M) + (v[vOff + 3] & M); + u[uOff + 3] = (int)c; + v[vOff + 3] = (int)c; + c >>>= 32; + c += (u[uOff + 4] & M) + (v[vOff + 4] & M); + u[uOff + 4] = (int)c; + v[vOff + 4] = (int)c; + c >>>= 32; + c += (u[uOff + 5] & M) + (v[vOff + 5] & M); + u[uOff + 5] = (int)c; + v[vOff + 5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static void copy(int[] x, int[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + } + + public static int[] create() + { + return new int[6]; + } + + public static int[] createExt() + { + return new int[12]; + } + + public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + boolean pos = gte(x, xOff, y, yOff); + if (pos) + { + sub(x, xOff, y, yOff, z, zOff); + } + else + { + sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static boolean eq(int[] x, int[] y) + { + for (int i = 5; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static int[] fromBigInteger(BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > 192) + { + throw new IllegalArgumentException(); + } + + int[] z = create(); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.intValue(); + x = x.shiftRight(32); + } + return z; + } + + public static int getBit(int[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= 6) + { + return 0; + } + int b = bit & 31; + return (x[w] >>> b) & 1; + } + + public static boolean gte(int[] x, int[] y) + { + for (int i = 5; i >= 0; --i) + { + int x_i = x[i] ^ Integer.MIN_VALUE; + int y_i = y[i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean gte(int[] x, int xOff, int[] y, int yOff) + { + for (int i = 5; i >= 0; --i) + { + int x_i = x[xOff + i] ^ Integer.MIN_VALUE; + int y_i = y[yOff + i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean isOne(int[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 6; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static boolean isZero(int[] x) + { + for (int i = 0; i < 6; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void mul(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + + { + long c = 0, x_0 = x[0] & M; + c += x_0 * y_0; + zz[0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[5] = (int)c; + c >>>= 32; + zz[6] = (int)c; + } + + for (int i = 1; i < 6; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + zz[i + 6] = (int)c; + } + } + + public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + + { + long c = 0, x_0 = x[xOff + 0] & M; + c += x_0 * y_0; + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (int)c; + c >>>= 32; + zz[zzOff + 6] = (int)c; + } + + for (int i = 1; i < 6; ++i) + { + ++zzOff; + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + zz[zzOff + 6] = (int)c; + } + } + + public static int mulAddTo(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + + long zc = 0; + for (int i = 0; i < 6; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + c += zc + (zz[i + 6] & M); + zz[i + 6] = (int)c; + zc = c >>> 32; + } + return (int)zc; + } + + public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + + long zc = 0; + for (int i = 0; i < 6; ++i) + { + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += zc + (zz[zzOff + 6] & M); + zz[zzOff + 6] = (int)c; + zc = c >>> 32; + ++zzOff; + } + return (int)zc; + } + + public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + // assert w >>> 31 == 0; + + long c = 0, wVal = w & M; + long x0 = x[xOff + 0] & M; + c += wVal * x0 + (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long x1 = x[xOff + 1] & M; + c += wVal * x1 + x0 + (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + long x2 = x[xOff + 2] & M; + c += wVal * x2 + x1 + (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + long x3 = x[xOff + 3] & M; + c += wVal * x3 + x2 + (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + long x4 = x[xOff + 4] & M; + c += wVal * x4 + x3 + (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + long x5 = x[xOff + 5] & M; + c += wVal * x5 + x4 + (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += x5; + return c; + } + + public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff) + { + // assert yyOff <= 6; + // assert zzOff <= 6; + long c = 0, xVal = x & M; + c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mul33DWordAdd(int x, long y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 2; + + long c = 0, xVal = x & M; + long y00 = y & M; + c += xVal * y00 + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long y01 = y >>> 32; + c += xVal * y01 + y00 + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += y01 + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4); + } + + public static int mul33WordAdd(int x, int y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 3; + + long c = 0, xVal = x & M, yVal = y & M; + c += yVal * xVal + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += yVal + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3); + } + + public static int mulWordDwordAdd(int x, long y, int[] z, int zOff) + { + // assert zOff <= 3; + long c = 0, xVal = x & M; + c += xVal * (y & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += xVal * (y >>> 32) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3); + } + + public static int mulWord(int x, int[] y, int[] z, int zOff) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < 6); + return (int)c; + } + + public static void square(int[] x, int[] zz) + { + long x_0 = x[0] & M; + long zz_1; + + int c = 0, w; + { + int i = 5, j = 12; + do + { + long xVal = (x[i--] & M); + long p = xVal * xVal; + zz[--j] = (c << 31) | (int)(p >>> 33); + zz[--j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[1] & M; + long zz_2 = zz[2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[2] & M; + long zz_3 = zz[3] & M; + long zz_4 = zz[4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[3] & M; + long zz_5 = zz[5] & M; + long zz_6 = zz[6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[4] & M; + long zz_7 = zz[7] & M; + long zz_8 = zz[8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[5] & M; + long zz_9 = zz[9] & M; + long zz_10 = zz[10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_10 += zz_9 >>> 32; + } + + w = (int)zz_6; + zz[6] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_7; + zz[7] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_8; + zz[8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[10] = (w << 1) | c; + c = w >>> 31; + w = zz[11] + (int)(zz_10 >> 32); + zz[11] = (w << 1) | c; + } + + public static void square(int[] x, int xOff, int[] zz, int zzOff) + { + long x_0 = x[xOff + 0] & M; + long zz_1; + + int c = 0, w; + { + int i = 5, j = 12; + do + { + long xVal = (x[xOff + i--] & M); + long p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (int)(p >>> 33); + zz[zzOff + --j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[zzOff + 0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[xOff + 1] & M; + long zz_2 = zz[zzOff + 2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[xOff + 2] & M; + long zz_3 = zz[zzOff + 3] & M; + long zz_4 = zz[zzOff + 4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[xOff + 3] & M; + long zz_5 = zz[zzOff + 5] & M; + long zz_6 = zz[zzOff + 6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[xOff + 4] & M; + long zz_7 = zz[zzOff + 7] & M; + long zz_8 = zz[zzOff + 8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[xOff + 5] & M; + long zz_9 = zz[zzOff + 9] & M; + long zz_10 = zz[zzOff + 10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_10 += zz_9 >>> 32; + } + + w = (int)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >>> 31; + w = zz[zzOff + 11] + (int)(zz_10 >> 32); + zz[zzOff + 11] = (w << 1) | c; + } + + public static int sub(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + return (int)c; + } + + public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) - (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (x[xOff + 1] & M) - (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (x[xOff + 2] & M) - (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (x[xOff + 3] & M) - (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (x[xOff + 4] & M) - (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (x[xOff + 5] & M) - (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subBothFrom(int[] x, int[] y, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M); + z[5] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int xOff, int[] z, int zOff) + { + long c = 0; + c += (z[zOff + 0] & M) - (x[xOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (z[zOff + 1] & M) - (x[xOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (z[zOff + 2] & M) - (x[xOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (z[zOff + 3] & M) - (x[xOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (z[zOff + 4] & M) - (x[xOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (z[zOff + 5] & M) - (x[xOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + return (int)c; + } + + public static BigInteger toBigInteger(int[] x) + { + byte[] bs = new byte[24]; + for (int i = 0; i < 6; ++i) + { + int x_i = x[i]; + if (x_i != 0) + { + Pack.intToBigEndian(x_i, bs, (5 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void zero(int[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat224.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat224.java new file mode 100644 index 000000000..8f4e47b8a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat224.java @@ -0,0 +1,1182 @@ +package org.spongycastle.math.raw; + +import java.math.BigInteger; + +import org.spongycastle.util.Pack; + +public abstract class Nat224 +{ + private static final long M = 0xFFFFFFFFL; + + public static int add(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (y[6] & M); + z[6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) + (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addBothTo(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (y[6] & M) + (z[6] & M); + z[6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int[] z) + { + long c = 0; + c += (x[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (z[6] & M); + z[6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn) + { + long c = cIn & M; + c += (x[xOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addToEachOther(int[] u, int uOff, int[] v, int vOff) + { + long c = 0; + c += (u[uOff + 0] & M) + (v[vOff + 0] & M); + u[uOff + 0] = (int)c; + v[vOff + 0] = (int)c; + c >>>= 32; + c += (u[uOff + 1] & M) + (v[vOff + 1] & M); + u[uOff + 1] = (int)c; + v[vOff + 1] = (int)c; + c >>>= 32; + c += (u[uOff + 2] & M) + (v[vOff + 2] & M); + u[uOff + 2] = (int)c; + v[vOff + 2] = (int)c; + c >>>= 32; + c += (u[uOff + 3] & M) + (v[vOff + 3] & M); + u[uOff + 3] = (int)c; + v[vOff + 3] = (int)c; + c >>>= 32; + c += (u[uOff + 4] & M) + (v[vOff + 4] & M); + u[uOff + 4] = (int)c; + v[vOff + 4] = (int)c; + c >>>= 32; + c += (u[uOff + 5] & M) + (v[vOff + 5] & M); + u[uOff + 5] = (int)c; + v[vOff + 5] = (int)c; + c >>>= 32; + c += (u[uOff + 6] & M) + (v[vOff + 6] & M); + u[uOff + 6] = (int)c; + v[vOff + 6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static void copy(int[] x, int[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + } + + public static int[] create() + { + return new int[7]; + } + + public static int[] createExt() + { + return new int[14]; + } + + public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + boolean pos = gte(x, xOff, y, yOff); + if (pos) + { + sub(x, xOff, y, yOff, z, zOff); + } + else + { + sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static boolean eq(int[] x, int[] y) + { + for (int i = 6; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static int[] fromBigInteger(BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > 224) + { + throw new IllegalArgumentException(); + } + + int[] z = create(); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.intValue(); + x = x.shiftRight(32); + } + return z; + } + + public static int getBit(int[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + int w = bit >> 5; + if (w < 0 || w >= 7) + { + return 0; + } + int b = bit & 31; + return (x[w] >>> b) & 1; + } + + public static boolean gte(int[] x, int[] y) + { + for (int i = 6; i >= 0; --i) + { + int x_i = x[i] ^ Integer.MIN_VALUE; + int y_i = y[i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean gte(int[] x, int xOff, int[] y, int yOff) + { + for (int i = 6; i >= 0; --i) + { + int x_i = x[xOff + i] ^ Integer.MIN_VALUE; + int y_i = y[yOff + i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean isOne(int[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 7; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static boolean isZero(int[] x) + { + for (int i = 0; i < 7; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void mul(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + long y_6 = y[6] & M; + + { + long c = 0, x_0 = x[0] & M; + c += x_0 * y_0; + zz[0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[5] = (int)c; + c >>>= 32; + c += x_0 * y_6; + zz[6] = (int)c; + c >>>= 32; + zz[7] = (int)c; + } + + for (int i = 1; i < 7; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[i + 6] & M); + zz[i + 6] = (int)c; + c >>>= 32; + zz[i + 7] = (int)c; + } + } + + public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + long y_6 = y[yOff + 6] & M; + + { + long c = 0, x_0 = x[xOff + 0] & M; + c += x_0 * y_0; + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_0 * y_6; + zz[zzOff + 6] = (int)c; + c >>>= 32; + zz[zzOff + 7] = (int)c; + } + + for (int i = 1; i < 7; ++i) + { + ++zzOff; + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[zzOff + 6] & M); + zz[zzOff + 6] = (int)c; + c >>>= 32; + zz[zzOff + 7] = (int)c; + } + } + + public static int mulAddTo(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + long y_6 = y[6] & M; + + long zc = 0; + for (int i = 0; i < 7; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[i + 6] & M); + zz[i + 6] = (int)c; + c >>>= 32; + c += zc + (zz[i + 7] & M); + zz[i + 7] = (int)c; + zc = c >>> 32; + } + return (int)zc; + } + + public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + long y_6 = y[yOff + 6] & M; + + long zc = 0; + for (int i = 0; i < 7; ++i) + { + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[zzOff + 6] & M); + zz[zzOff + 6] = (int)c; + c >>>= 32; + c += zc + (zz[zzOff + 7] & M); + zz[zzOff + 7] = (int)c; + zc = c >>> 32; + ++zzOff; + } + return (int)zc; + } + + public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + // assert w >>> 31 == 0; + + long c = 0, wVal = w & M; + long x0 = x[xOff + 0] & M; + c += wVal * x0 + (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long x1 = x[xOff + 1] & M; + c += wVal * x1 + x0 + (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + long x2 = x[xOff + 2] & M; + c += wVal * x2 + x1 + (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + long x3 = x[xOff + 3] & M; + c += wVal * x3 + x2 + (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + long x4 = x[xOff + 4] & M; + c += wVal * x4 + x3 + (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + long x5 = x[xOff + 5] & M; + c += wVal * x5 + x4 + (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + long x6 = x[xOff + 6] & M; + c += wVal * x6 + x5 + (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + c += x6; + return c; + } + + public static int mulByWord(int x, int[] z) + { + long c = 0, xVal = x & M; + c += xVal * (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += xVal * (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += xVal * (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += xVal * (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += xVal * (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += xVal * (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += xVal * (z[6] & M); + z[6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mulByWordAddTo(int x, int[] y, int[] z) + { + long c = 0, xVal = x & M; + c += xVal * (z[0] & M) + (y[0] & M); + z[0] = (int)c; + c >>>= 32; + c += xVal * (z[1] & M) + (y[1] & M); + z[1] = (int)c; + c >>>= 32; + c += xVal * (z[2] & M) + (y[2] & M); + z[2] = (int)c; + c >>>= 32; + c += xVal * (z[3] & M) + (y[3] & M); + z[3] = (int)c; + c >>>= 32; + c += xVal * (z[4] & M) + (y[4] & M); + z[4] = (int)c; + c >>>= 32; + c += xVal * (z[5] & M) + (y[5] & M); + z[5] = (int)c; + c >>>= 32; + c += xVal * (z[6] & M) + (y[6] & M); + z[6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff) + { + long c = 0, xVal = x & M; + c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mul33DWordAdd(int x, long y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 3; + + long c = 0, xVal = x & M; + long y00 = y & M; + c += xVal * y00 + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long y01 = y >>> 32; + c += xVal * y01 + y00 + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += y01 + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(7, z, zOff, 4); + } + + public static int mul33WordAdd(int x, int y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 4; + + long c = 0, xVal = x & M, yVal = y & M; + c += yVal * xVal + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += yVal + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3); + } + + public static int mulWordDwordAdd(int x, long y, int[] z, int zOff) + { + // assert zOff <= 4; + long c = 0, xVal = x & M; + c += xVal * (y & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += xVal * (y >>> 32) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(7, z, zOff, 3); + } + + public static int mulWord(int x, int[] y, int[] z, int zOff) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < 7); + return (int)c; + } + + public static void square(int[] x, int[] zz) + { + long x_0 = x[0] & M; + long zz_1; + + int c = 0, w; + { + int i = 6, j = 14; + do + { + long xVal = (x[i--] & M); + long p = xVal * xVal; + zz[--j] = (c << 31) | (int)(p >>> 33); + zz[--j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[1] & M; + long zz_2 = zz[2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[2] & M; + long zz_3 = zz[3] & M; + long zz_4 = zz[4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[3] & M; + long zz_5 = zz[5] & M; + long zz_6 = zz[6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[4] & M; + long zz_7 = zz[7] & M; + long zz_8 = zz[8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[5] & M; + long zz_9 = zz[9] & M; + long zz_10 = zz[10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >>> 32; + zz_9 &= M; + } + + long x_6 = x[6] & M; + long zz_11 = zz[11] & M; + long zz_12 = zz[12] & M; + { + zz_6 += x_6 * x_0; + w = (int)zz_6; + zz[6] = (w << 1) | c; + c = w >>> 31; + zz_7 += (zz_6 >>> 32) + x_6 * x_1; + zz_8 += (zz_7 >>> 32) + x_6 * x_2; + zz_9 += (zz_8 >>> 32) + x_6 * x_3; + zz_10 += (zz_9 >>> 32) + x_6 * x_4; + zz_11 += (zz_10 >>> 32) + x_6 * x_5; + zz_12 += zz_11 >>> 32; + } + + w = (int)zz_7; + zz[7] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_8; + zz[8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[10] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_11; + zz[11] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_12; + zz[12] = (w << 1) | c; + c = w >>> 31; + w = zz[13] + (int)(zz_12 >> 32); + zz[13] = (w << 1) | c; + } + + public static void square(int[] x, int xOff, int[] zz, int zzOff) + { + long x_0 = x[xOff + 0] & M; + long zz_1; + + int c = 0, w; + { + int i = 6, j = 14; + do + { + long xVal = (x[xOff + i--] & M); + long p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (int)(p >>> 33); + zz[zzOff + --j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[zzOff + 0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[xOff + 1] & M; + long zz_2 = zz[zzOff + 2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[xOff + 2] & M; + long zz_3 = zz[zzOff + 3] & M; + long zz_4 = zz[zzOff + 4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[xOff + 3] & M; + long zz_5 = zz[zzOff + 5] & M; + long zz_6 = zz[zzOff + 6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[xOff + 4] & M; + long zz_7 = zz[zzOff + 7] & M; + long zz_8 = zz[zzOff + 8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[xOff + 5] & M; + long zz_9 = zz[zzOff + 9] & M; + long zz_10 = zz[zzOff + 10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >>> 32; + zz_9 &= M; + } + + long x_6 = x[xOff + 6] & M; + long zz_11 = zz[zzOff + 11] & M; + long zz_12 = zz[zzOff + 12] & M; + { + zz_6 += x_6 * x_0; + w = (int)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >>> 31; + zz_7 += (zz_6 >>> 32) + x_6 * x_1; + zz_8 += (zz_7 >>> 32) + x_6 * x_2; + zz_9 += (zz_8 >>> 32) + x_6 * x_3; + zz_10 += (zz_9 >>> 32) + x_6 * x_4; + zz_11 += (zz_10 >>> 32) + x_6 * x_5; + zz_12 += zz_11 >>> 32; + } + + w = (int)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_11; + zz[zzOff + 11] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_12; + zz[zzOff + 12] = (w << 1) | c; + c = w >>> 31; + w = zz[zzOff + 13] + (int)(zz_12 >> 32); + zz[zzOff + 13] = (w << 1) | c; + } + + public static int sub(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + c += (x[6] & M) - (y[6] & M); + z[6] = (int)c; + c >>= 32; + return (int)c; + } + + public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) - (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (x[xOff + 1] & M) - (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (x[xOff + 2] & M) - (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (x[xOff + 3] & M) - (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (x[xOff + 4] & M) - (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (x[xOff + 5] & M) - (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + c += (x[xOff + 6] & M) - (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subBothFrom(int[] x, int[] y, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + c += (z[6] & M) - (x[6] & M) - (y[6] & M); + z[6] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M); + z[5] = (int)c; + c >>= 32; + c += (z[6] & M) - (x[6] & M); + z[6] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int xOff, int[] z, int zOff) + { + long c = 0; + c += (z[zOff + 0] & M) - (x[xOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (z[zOff + 1] & M) - (x[xOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (z[zOff + 2] & M) - (x[xOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (z[zOff + 3] & M) - (x[xOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (z[zOff + 4] & M) - (x[xOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (z[zOff + 5] & M) - (x[xOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + c += (z[zOff + 6] & M) - (x[xOff + 6] & M); + z[zOff + 6] = (int)c; + c >>= 32; + return (int)c; + } + + public static BigInteger toBigInteger(int[] x) + { + byte[] bs = new byte[28]; + for (int i = 0; i < 7; ++i) + { + int x_i = x[i]; + if (x_i != 0) + { + Pack.intToBigEndian(x_i, bs, (6 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void zero(int[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + z[6] = 0; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat256.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat256.java new file mode 100644 index 000000000..3cbf1ae7a --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat256.java @@ -0,0 +1,1306 @@ +package org.spongycastle.math.raw; + +import java.math.BigInteger; + +import org.spongycastle.util.Pack; + +public abstract class Nat256 +{ + private static final long M = 0xFFFFFFFFL; + + public static int add(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (y[6] & M); + z[6] = (int)c; + c >>>= 32; + c += (x[7] & M) + (y[7] & M); + z[7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) + (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + c += (x[xOff + 7] & M) + (y[yOff + 7] & M); + z[zOff + 7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addBothTo(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) + (y[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (y[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (y[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (y[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (y[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (y[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (y[6] & M) + (z[6] & M); + z[6] = (int)c; + c >>>= 32; + c += (x[7] & M) + (y[7] & M) + (z[7] & M); + z[7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M); + z[zOff + 7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int[] z) + { + long c = 0; + c += (x[0] & M) + (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += (x[1] & M) + (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += (x[2] & M) + (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += (x[3] & M) + (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += (x[4] & M) + (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += (x[5] & M) + (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += (x[6] & M) + (z[6] & M); + z[6] = (int)c; + c >>>= 32; + c += (x[7] & M) + (z[7] & M); + z[7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn) + { + long c = cIn & M; + c += (x[xOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += (x[xOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (x[xOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (x[xOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += (x[xOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += (x[xOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += (x[xOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + c += (x[xOff + 7] & M) + (z[zOff + 7] & M); + z[zOff + 7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int addToEachOther(int[] u, int uOff, int[] v, int vOff) + { + long c = 0; + c += (u[uOff + 0] & M) + (v[vOff + 0] & M); + u[uOff + 0] = (int)c; + v[vOff + 0] = (int)c; + c >>>= 32; + c += (u[uOff + 1] & M) + (v[vOff + 1] & M); + u[uOff + 1] = (int)c; + v[vOff + 1] = (int)c; + c >>>= 32; + c += (u[uOff + 2] & M) + (v[vOff + 2] & M); + u[uOff + 2] = (int)c; + v[vOff + 2] = (int)c; + c >>>= 32; + c += (u[uOff + 3] & M) + (v[vOff + 3] & M); + u[uOff + 3] = (int)c; + v[vOff + 3] = (int)c; + c >>>= 32; + c += (u[uOff + 4] & M) + (v[vOff + 4] & M); + u[uOff + 4] = (int)c; + v[vOff + 4] = (int)c; + c >>>= 32; + c += (u[uOff + 5] & M) + (v[vOff + 5] & M); + u[uOff + 5] = (int)c; + v[vOff + 5] = (int)c; + c >>>= 32; + c += (u[uOff + 6] & M) + (v[vOff + 6] & M); + u[uOff + 6] = (int)c; + v[vOff + 6] = (int)c; + c >>>= 32; + c += (u[uOff + 7] & M) + (v[vOff + 7] & M); + u[uOff + 7] = (int)c; + v[vOff + 7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static void copy(int[] x, int[] z) + { + z[0] = x[0]; + z[1] = x[1]; + z[2] = x[2]; + z[3] = x[3]; + z[4] = x[4]; + z[5] = x[5]; + z[6] = x[6]; + z[7] = x[7]; + } + + public static int[] create() + { + return new int[8]; + } + + public static int[] createExt() + { + return new int[16]; + } + + public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + boolean pos = gte(x, xOff, y, yOff); + if (pos) + { + sub(x, xOff, y, yOff, z, zOff); + } + else + { + sub(y, yOff, x, xOff, z, zOff); + } + return pos; + } + + public static boolean eq(int[] x, int[] y) + { + for (int i = 7; i >= 0; --i) + { + if (x[i] != y[i]) + { + return false; + } + } + return true; + } + + public static int[] fromBigInteger(BigInteger x) + { + if (x.signum() < 0 || x.bitLength() > 256) + { + throw new IllegalArgumentException(); + } + + int[] z = create(); + int i = 0; + while (x.signum() != 0) + { + z[i++] = x.intValue(); + x = x.shiftRight(32); + } + return z; + } + + public static int getBit(int[] x, int bit) + { + if (bit == 0) + { + return x[0] & 1; + } + if ((bit & 255) != bit) + { + return 0; + } + int w = bit >>> 5; + int b = bit & 31; + return (x[w] >>> b) & 1; + } + + public static boolean gte(int[] x, int[] y) + { + for (int i = 7; i >= 0; --i) + { + int x_i = x[i] ^ Integer.MIN_VALUE; + int y_i = y[i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean gte(int[] x, int xOff, int[] y, int yOff) + { + for (int i = 7; i >= 0; --i) + { + int x_i = x[xOff + i] ^ Integer.MIN_VALUE; + int y_i = y[yOff + i] ^ Integer.MIN_VALUE; + if (x_i < y_i) + return false; + if (x_i > y_i) + return true; + } + return true; + } + + public static boolean isOne(int[] x) + { + if (x[0] != 1) + { + return false; + } + for (int i = 1; i < 8; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static boolean isZero(int[] x) + { + for (int i = 0; i < 8; ++i) + { + if (x[i] != 0) + { + return false; + } + } + return true; + } + + public static void mul(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + long y_6 = y[6] & M; + long y_7 = y[7] & M; + + { + long c = 0, x_0 = x[0] & M; + c += x_0 * y_0; + zz[0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[5] = (int)c; + c >>>= 32; + c += x_0 * y_6; + zz[6] = (int)c; + c >>>= 32; + c += x_0 * y_7; + zz[7] = (int)c; + c >>>= 32; + zz[8] = (int)c; + } + + for (int i = 1; i < 8; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[i + 6] & M); + zz[i + 6] = (int)c; + c >>>= 32; + c += x_i * y_7 + (zz[i + 7] & M); + zz[i + 7] = (int)c; + c >>>= 32; + zz[i + 8] = (int)c; + } + } + + public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + long y_6 = y[yOff + 6] & M; + long y_7 = y[yOff + 7] & M; + + { + long c = 0, x_0 = x[xOff + 0] & M; + c += x_0 * y_0; + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_0 * y_1; + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_0 * y_2; + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_0 * y_3; + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_0 * y_4; + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_0 * y_5; + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_0 * y_6; + zz[zzOff + 6] = (int)c; + c >>>= 32; + c += x_0 * y_7; + zz[zzOff + 7] = (int)c; + c >>>= 32; + zz[zzOff + 8] = (int)c; + } + + for (int i = 1; i < 8; ++i) + { + ++zzOff; + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[zzOff + 6] & M); + zz[zzOff + 6] = (int)c; + c >>>= 32; + c += x_i * y_7 + (zz[zzOff + 7] & M); + zz[zzOff + 7] = (int)c; + c >>>= 32; + zz[zzOff + 8] = (int)c; + } + } + + public static int mulAddTo(int[] x, int[] y, int[] zz) + { + long y_0 = y[0] & M; + long y_1 = y[1] & M; + long y_2 = y[2] & M; + long y_3 = y[3] & M; + long y_4 = y[4] & M; + long y_5 = y[5] & M; + long y_6 = y[6] & M; + long y_7 = y[7] & M; + + long zc = 0; + for (int i = 0; i < 8; ++i) + { + long c = 0, x_i = x[i] & M; + c += x_i * y_0 + (zz[i + 0] & M); + zz[i + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[i + 1] & M); + zz[i + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[i + 2] & M); + zz[i + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[i + 3] & M); + zz[i + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[i + 4] & M); + zz[i + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[i + 5] & M); + zz[i + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[i + 6] & M); + zz[i + 6] = (int)c; + c >>>= 32; + c += x_i * y_7 + (zz[i + 7] & M); + zz[i + 7] = (int)c; + c >>>= 32; + c += zc + (zz[i + 8] & M); + zz[i + 8] = (int)c; + zc = c >>> 32; + } + return (int)zc; + } + + public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) + { + long y_0 = y[yOff + 0] & M; + long y_1 = y[yOff + 1] & M; + long y_2 = y[yOff + 2] & M; + long y_3 = y[yOff + 3] & M; + long y_4 = y[yOff + 4] & M; + long y_5 = y[yOff + 5] & M; + long y_6 = y[yOff + 6] & M; + long y_7 = y[yOff + 7] & M; + + long zc = 0; + for (int i = 0; i < 8; ++i) + { + long c = 0, x_i = x[xOff + i] & M; + c += x_i * y_0 + (zz[zzOff + 0] & M); + zz[zzOff + 0] = (int)c; + c >>>= 32; + c += x_i * y_1 + (zz[zzOff + 1] & M); + zz[zzOff + 1] = (int)c; + c >>>= 32; + c += x_i * y_2 + (zz[zzOff + 2] & M); + zz[zzOff + 2] = (int)c; + c >>>= 32; + c += x_i * y_3 + (zz[zzOff + 3] & M); + zz[zzOff + 3] = (int)c; + c >>>= 32; + c += x_i * y_4 + (zz[zzOff + 4] & M); + zz[zzOff + 4] = (int)c; + c >>>= 32; + c += x_i * y_5 + (zz[zzOff + 5] & M); + zz[zzOff + 5] = (int)c; + c >>>= 32; + c += x_i * y_6 + (zz[zzOff + 6] & M); + zz[zzOff + 6] = (int)c; + c >>>= 32; + c += x_i * y_7 + (zz[zzOff + 7] & M); + zz[zzOff + 7] = (int)c; + c >>>= 32; + c += zc + (zz[zzOff + 8] & M); + zz[zzOff + 8] = (int)c; + zc = c >>> 32; + ++zzOff; + } + return (int)zc; + } + + public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + // assert w >>> 31 == 0; + + long c = 0, wVal = w & M; + long x0 = x[xOff + 0] & M; + c += wVal * x0 + (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long x1 = x[xOff + 1] & M; + c += wVal * x1 + x0 + (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + long x2 = x[xOff + 2] & M; + c += wVal * x2 + x1 + (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + long x3 = x[xOff + 3] & M; + c += wVal * x3 + x2 + (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + long x4 = x[xOff + 4] & M; + c += wVal * x4 + x3 + (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + long x5 = x[xOff + 5] & M; + c += wVal * x5 + x4 + (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + long x6 = x[xOff + 6] & M; + c += wVal * x6 + x5 + (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + long x7 = x[xOff + 7] & M; + c += wVal * x7 + x6 + (y[yOff + 7] & M); + z[zOff + 7] = (int)c; + c >>>= 32; + c += x7; + return c; + } + + public static int mulByWord(int x, int[] z) + { + long c = 0, xVal = x & M; + c += xVal * (z[0] & M); + z[0] = (int)c; + c >>>= 32; + c += xVal * (z[1] & M); + z[1] = (int)c; + c >>>= 32; + c += xVal * (z[2] & M); + z[2] = (int)c; + c >>>= 32; + c += xVal * (z[3] & M); + z[3] = (int)c; + c >>>= 32; + c += xVal * (z[4] & M); + z[4] = (int)c; + c >>>= 32; + c += xVal * (z[5] & M); + z[5] = (int)c; + c >>>= 32; + c += xVal * (z[6] & M); + z[6] = (int)c; + c >>>= 32; + c += xVal * (z[7] & M); + z[7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mulByWordAddTo(int x, int[] y, int[] z) + { + long c = 0, xVal = x & M; + c += xVal * (z[0] & M) + (y[0] & M); + z[0] = (int)c; + c >>>= 32; + c += xVal * (z[1] & M) + (y[1] & M); + z[1] = (int)c; + c >>>= 32; + c += xVal * (z[2] & M) + (y[2] & M); + z[2] = (int)c; + c >>>= 32; + c += xVal * (z[3] & M) + (y[3] & M); + z[3] = (int)c; + c >>>= 32; + c += xVal * (z[4] & M) + (y[4] & M); + z[4] = (int)c; + c >>>= 32; + c += xVal * (z[5] & M) + (y[5] & M); + z[5] = (int)c; + c >>>= 32; + c += xVal * (z[6] & M) + (y[6] & M); + z[6] = (int)c; + c >>>= 32; + c += xVal * (z[7] & M) + (y[7] & M); + z[7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff) + { + long c = 0, xVal = x & M; + c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M); + z[zOff + 4] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M); + z[zOff + 5] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M); + z[zOff + 6] = (int)c; + c >>>= 32; + c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M); + z[zOff + 7] = (int)c; + c >>>= 32; + return (int)c; + } + + public static int mul33DWordAdd(int x, long y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 4; + + long c = 0, xVal = x & M; + long y00 = y & M; + c += xVal * y00 + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + long y01 = y >>> 32; + c += xVal * y01 + y00 + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += y01 + (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + c += (z[zOff + 3] & M); + z[zOff + 3] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4); + } + + public static int mul33WordAdd(int x, int y, int[] z, int zOff) + { + // assert x >>> 31 == 0; + // assert zOff <= 5; + + long c = 0, xVal = x & M, yVal = y & M; + c += yVal * xVal + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += yVal + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3); + } + + public static int mulWordDwordAdd(int x, long y, int[] z, int zOff) + { + // assert zOff <= 5; + long c = 0, xVal = x & M; + c += xVal * (y & M) + (z[zOff + 0] & M); + z[zOff + 0] = (int)c; + c >>>= 32; + c += xVal * (y >>> 32) + (z[zOff + 1] & M); + z[zOff + 1] = (int)c; + c >>>= 32; + c += (z[zOff + 2] & M); + z[zOff + 2] = (int)c; + c >>>= 32; + return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3); + } + + public static int mulWord(int x, int[] y, int[] z, int zOff) + { + long c = 0, xVal = x & M; + int i = 0; + do + { + c += xVal * (y[i] & M); + z[zOff + i] = (int)c; + c >>>= 32; + } + while (++i < 8); + return (int)c; + } + + public static void square(int[] x, int[] zz) + { + long x_0 = x[0] & M; + long zz_1; + + int c = 0, w; + { + int i = 7, j = 16; + do + { + long xVal = (x[i--] & M); + long p = xVal * xVal; + zz[--j] = (c << 31) | (int)(p >>> 33); + zz[--j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[1] & M; + long zz_2 = zz[2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[2] & M; + long zz_3 = zz[3] & M; + long zz_4 = zz[4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[3] & M; + long zz_5 = zz[5] & M; + long zz_6 = zz[6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[4] & M; + long zz_7 = zz[7] & M; + long zz_8 = zz[8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[5] & M; + long zz_9 = zz[9] & M; + long zz_10 = zz[10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >>> 32; + zz_9 &= M; + } + + long x_6 = x[6] & M; + long zz_11 = zz[11] & M; + long zz_12 = zz[12] & M; + { + zz_6 += x_6 * x_0; + w = (int)zz_6; + zz[6] = (w << 1) | c; + c = w >>> 31; + zz_7 += (zz_6 >>> 32) + x_6 * x_1; + zz_8 += (zz_7 >>> 32) + x_6 * x_2; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_6 * x_3; + zz_8 &= M; + zz_10 += (zz_9 >>> 32) + x_6 * x_4; + zz_9 &= M; + zz_11 += (zz_10 >>> 32) + x_6 * x_5; + zz_10 &= M; + zz_12 += zz_11 >>> 32; + zz_11 &= M; + } + + long x_7 = x[7] & M; + long zz_13 = zz[13] & M; + long zz_14 = zz[14] & M; + { + zz_7 += x_7 * x_0; + w = (int)zz_7; + zz[7] = (w << 1) | c; + c = w >>> 31; + zz_8 += (zz_7 >>> 32) + x_7 * x_1; + zz_9 += (zz_8 >>> 32) + x_7 * x_2; + zz_10 += (zz_9 >>> 32) + x_7 * x_3; + zz_11 += (zz_10 >>> 32) + x_7 * x_4; + zz_12 += (zz_11 >>> 32) + x_7 * x_5; + zz_13 += (zz_12 >>> 32) + x_7 * x_6; + zz_14 += zz_13 >>> 32; + } + + w = (int)zz_8; + zz[8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[10] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_11; + zz[11] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_12; + zz[12] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_13; + zz[13] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_14; + zz[14] = (w << 1) | c; + c = w >>> 31; + w = zz[15] + (int)(zz_14 >> 32); + zz[15] = (w << 1) | c; + } + + public static void square(int[] x, int xOff, int[] zz, int zzOff) + { + long x_0 = x[xOff + 0] & M; + long zz_1; + + int c = 0, w; + { + int i = 7, j = 16; + do + { + long xVal = (x[xOff + i--] & M); + long p = xVal * xVal; + zz[zzOff + --j] = (c << 31) | (int)(p >>> 33); + zz[zzOff + --j] = (int)(p >>> 1); + c = (int)p; + } + while (i > 0); + + { + long p = x_0 * x_0; + zz_1 = ((c << 31) & M) | (p >>> 33); + zz[zzOff + 0] = (int)p; + c = (int)(p >>> 32) & 1; + } + } + + long x_1 = x[xOff + 1] & M; + long zz_2 = zz[zzOff + 2] & M; + + { + zz_1 += x_1 * x_0; + w = (int)zz_1; + zz[zzOff + 1] = (w << 1) | c; + c = w >>> 31; + zz_2 += zz_1 >>> 32; + } + + long x_2 = x[xOff + 2] & M; + long zz_3 = zz[zzOff + 3] & M; + long zz_4 = zz[zzOff + 4] & M; + { + zz_2 += x_2 * x_0; + w = (int)zz_2; + zz[zzOff + 2] = (w << 1) | c; + c = w >>> 31; + zz_3 += (zz_2 >>> 32) + x_2 * x_1; + zz_4 += zz_3 >>> 32; + zz_3 &= M; + } + + long x_3 = x[xOff + 3] & M; + long zz_5 = zz[zzOff + 5] & M; + long zz_6 = zz[zzOff + 6] & M; + { + zz_3 += x_3 * x_0; + w = (int)zz_3; + zz[zzOff + 3] = (w << 1) | c; + c = w >>> 31; + zz_4 += (zz_3 >>> 32) + x_3 * x_1; + zz_5 += (zz_4 >>> 32) + x_3 * x_2; + zz_4 &= M; + zz_6 += zz_5 >>> 32; + zz_5 &= M; + } + + long x_4 = x[xOff + 4] & M; + long zz_7 = zz[zzOff + 7] & M; + long zz_8 = zz[zzOff + 8] & M; + { + zz_4 += x_4 * x_0; + w = (int)zz_4; + zz[zzOff + 4] = (w << 1) | c; + c = w >>> 31; + zz_5 += (zz_4 >>> 32) + x_4 * x_1; + zz_6 += (zz_5 >>> 32) + x_4 * x_2; + zz_5 &= M; + zz_7 += (zz_6 >>> 32) + x_4 * x_3; + zz_6 &= M; + zz_8 += zz_7 >>> 32; + zz_7 &= M; + } + + long x_5 = x[xOff + 5] & M; + long zz_9 = zz[zzOff + 9] & M; + long zz_10 = zz[zzOff + 10] & M; + { + zz_5 += x_5 * x_0; + w = (int)zz_5; + zz[zzOff + 5] = (w << 1) | c; + c = w >>> 31; + zz_6 += (zz_5 >>> 32) + x_5 * x_1; + zz_7 += (zz_6 >>> 32) + x_5 * x_2; + zz_6 &= M; + zz_8 += (zz_7 >>> 32) + x_5 * x_3; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_5 * x_4; + zz_8 &= M; + zz_10 += zz_9 >>> 32; + zz_9 &= M; + } + + long x_6 = x[xOff + 6] & M; + long zz_11 = zz[zzOff + 11] & M; + long zz_12 = zz[zzOff + 12] & M; + { + zz_6 += x_6 * x_0; + w = (int)zz_6; + zz[zzOff + 6] = (w << 1) | c; + c = w >>> 31; + zz_7 += (zz_6 >>> 32) + x_6 * x_1; + zz_8 += (zz_7 >>> 32) + x_6 * x_2; + zz_7 &= M; + zz_9 += (zz_8 >>> 32) + x_6 * x_3; + zz_8 &= M; + zz_10 += (zz_9 >>> 32) + x_6 * x_4; + zz_9 &= M; + zz_11 += (zz_10 >>> 32) + x_6 * x_5; + zz_10 &= M; + zz_12 += zz_11 >>> 32; + zz_11 &= M; + } + + long x_7 = x[xOff + 7] & M; + long zz_13 = zz[zzOff + 13] & M; + long zz_14 = zz[zzOff + 14] & M; + { + zz_7 += x_7 * x_0; + w = (int)zz_7; + zz[zzOff + 7] = (w << 1) | c; + c = w >>> 31; + zz_8 += (zz_7 >>> 32) + x_7 * x_1; + zz_9 += (zz_8 >>> 32) + x_7 * x_2; + zz_10 += (zz_9 >>> 32) + x_7 * x_3; + zz_11 += (zz_10 >>> 32) + x_7 * x_4; + zz_12 += (zz_11 >>> 32) + x_7 * x_5; + zz_13 += (zz_12 >>> 32) + x_7 * x_6; + zz_14 += zz_13 >>> 32; + } + + w = (int)zz_8; + zz[zzOff + 8] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_9; + zz[zzOff + 9] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_10; + zz[zzOff + 10] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_11; + zz[zzOff + 11] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_12; + zz[zzOff + 12] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_13; + zz[zzOff + 13] = (w << 1) | c; + c = w >>> 31; + w = (int)zz_14; + zz[zzOff + 14] = (w << 1) | c; + c = w >>> 31; + w = zz[zzOff + 15] + (int)(zz_14 >> 32); + zz[zzOff + 15] = (w << 1) | c; + } + + public static int sub(int[] x, int[] y, int[] z) + { + long c = 0; + c += (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + c += (x[6] & M) - (y[6] & M); + z[6] = (int)c; + c >>= 32; + c += (x[7] & M) - (y[7] & M); + z[7] = (int)c; + c >>= 32; + return (int)c; + } + + public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) + { + long c = 0; + c += (x[xOff + 0] & M) - (y[yOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (x[xOff + 1] & M) - (y[yOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (x[xOff + 2] & M) - (y[yOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (x[xOff + 3] & M) - (y[yOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (x[xOff + 4] & M) - (y[yOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (x[xOff + 5] & M) - (y[yOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + c += (x[xOff + 6] & M) - (y[yOff + 6] & M); + z[zOff + 6] = (int)c; + c >>= 32; + c += (x[xOff + 7] & M) - (y[yOff + 7] & M); + z[zOff + 7] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subBothFrom(int[] x, int[] y, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M) - (y[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M) - (y[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M) - (y[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M) - (y[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M) - (y[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M) - (y[5] & M); + z[5] = (int)c; + c >>= 32; + c += (z[6] & M) - (x[6] & M) - (y[6] & M); + z[6] = (int)c; + c >>= 32; + c += (z[7] & M) - (x[7] & M) - (y[7] & M); + z[7] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int[] z) + { + long c = 0; + c += (z[0] & M) - (x[0] & M); + z[0] = (int)c; + c >>= 32; + c += (z[1] & M) - (x[1] & M); + z[1] = (int)c; + c >>= 32; + c += (z[2] & M) - (x[2] & M); + z[2] = (int)c; + c >>= 32; + c += (z[3] & M) - (x[3] & M); + z[3] = (int)c; + c >>= 32; + c += (z[4] & M) - (x[4] & M); + z[4] = (int)c; + c >>= 32; + c += (z[5] & M) - (x[5] & M); + z[5] = (int)c; + c >>= 32; + c += (z[6] & M) - (x[6] & M); + z[6] = (int)c; + c >>= 32; + c += (z[7] & M) - (x[7] & M); + z[7] = (int)c; + c >>= 32; + return (int)c; + } + + public static int subFrom(int[] x, int xOff, int[] z, int zOff) + { + long c = 0; + c += (z[zOff + 0] & M) - (x[xOff + 0] & M); + z[zOff + 0] = (int)c; + c >>= 32; + c += (z[zOff + 1] & M) - (x[xOff + 1] & M); + z[zOff + 1] = (int)c; + c >>= 32; + c += (z[zOff + 2] & M) - (x[xOff + 2] & M); + z[zOff + 2] = (int)c; + c >>= 32; + c += (z[zOff + 3] & M) - (x[xOff + 3] & M); + z[zOff + 3] = (int)c; + c >>= 32; + c += (z[zOff + 4] & M) - (x[xOff + 4] & M); + z[zOff + 4] = (int)c; + c >>= 32; + c += (z[zOff + 5] & M) - (x[xOff + 5] & M); + z[zOff + 5] = (int)c; + c >>= 32; + c += (z[zOff + 6] & M) - (x[xOff + 6] & M); + z[zOff + 6] = (int)c; + c >>= 32; + c += (z[zOff + 7] & M) - (x[xOff + 7] & M); + z[zOff + 7] = (int)c; + c >>= 32; + return (int)c; + } + + public static BigInteger toBigInteger(int[] x) + { + byte[] bs = new byte[32]; + for (int i = 0; i < 8; ++i) + { + int x_i = x[i]; + if (x_i != 0) + { + Pack.intToBigEndian(x_i, bs, (7 - i) << 2); + } + } + return new BigInteger(1, bs); + } + + public static void zero(int[] z) + { + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + z[4] = 0; + z[5] = 0; + z[6] = 0; + z[7] = 0; + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat384.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat384.java new file mode 100644 index 000000000..d5b4b23c3 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat384.java @@ -0,0 +1,43 @@ +package org.spongycastle.math.raw; + + +public abstract class Nat384 +{ + public static void mul(int[] x, int[] y, int[] zz) + { + Nat192.mul(x, y, zz); + Nat192.mul(x, 6, y, 6, zz, 12); + + int c18 = Nat192.addToEachOther(zz, 6, zz, 12); + int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0); + c18 += Nat192.addTo(zz, 18, zz, 12, c12); + + int[] dx = Nat192.create(), dy = Nat192.create(); + boolean neg = Nat192.diff(x, 6, x, 0, dx, 0) != Nat192.diff(y, 6, y, 0, dy, 0); + + int[] tt = Nat192.createExt(); + Nat192.mul(dx, dy, tt); + + c18 += neg ? Nat.addTo(12, tt, 0, zz, 6) : Nat.subFrom(12, tt, 0, zz, 6); + Nat.addWordAt(24, c18, zz, 18); + } + + public static void square(int[] x, int[] zz) + { + Nat192.square(x, zz); + Nat192.square(x, 6, zz, 12); + + int c18 = Nat192.addToEachOther(zz, 6, zz, 12); + int c12 = c18 + Nat192.addTo(zz, 0, zz, 6, 0); + c18 += Nat192.addTo(zz, 18, zz, 12, c12); + + int[] dx = Nat192.create(); + Nat192.diff(x, 6, x, 0, dx, 0); + + int[] tt = Nat192.createExt(); + Nat192.square(dx, tt); + + c18 += Nat.subFrom(12, tt, 0, zz, 6); + Nat.addWordAt(24, c18, zz, 18); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat512.java b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat512.java new file mode 100644 index 000000000..1b32342b2 --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/math/raw/Nat512.java @@ -0,0 +1,43 @@ +package org.spongycastle.math.raw; + + +public abstract class Nat512 +{ + public static void mul(int[] x, int[] y, int[] zz) + { + Nat256.mul(x, y, zz); + Nat256.mul(x, 8, y, 8, zz, 16); + + int c24 = Nat256.addToEachOther(zz, 8, zz, 16); + int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0); + c24 += Nat256.addTo(zz, 24, zz, 16, c16); + + int[] dx = Nat256.create(), dy = Nat256.create(); + boolean neg = Nat256.diff(x, 8, x, 0, dx, 0) != Nat256.diff(y, 8, y, 0, dy, 0); + + int[] tt = Nat256.createExt(); + Nat256.mul(dx, dy, tt); + + c24 += neg ? Nat.addTo(16, tt, 0, zz, 8) : Nat.subFrom(16, tt, 0, zz, 8); + Nat.addWordAt(32, c24, zz, 24); + } + + public static void square(int[] x, int[] zz) + { + Nat256.square(x, zz); + Nat256.square(x, 8, zz, 16); + + int c24 = Nat256.addToEachOther(zz, 8, zz, 16); + int c16 = c24 + Nat256.addTo(zz, 0, zz, 8, 0); + c24 += Nat256.addTo(zz, 24, zz, 16, c16); + + int[] dx = Nat256.create(); + Nat256.diff(x, 8, x, 0, dx, 0); + + int[] tt = Nat256.createExt(); + Nat256.square(dx, tt); + + c24 += Nat.subFrom(16, tt, 0, zz, 8); + Nat.addWordAt(32, c24, zz, 24); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java index dcf83f2a9..779922837 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/GMSSPublicKey.java @@ -13,7 +13,6 @@ import org.spongycastle.util.Arrays; /** * This class implements an ASN.1 encoded GMSS public key. The ASN.1 definition * of this structure is: - ** GMSSPublicKey ::= SEQUENCE{ * version INTEGER diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java index 4914e940f..966489004 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java @@ -14,9 +14,8 @@ import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil; /** * Return the key data to encode in the PrivateKeyInfo structure. - * + ** The ASN.1 definition of the key structure is - *
** RainbowPrivateKey ::= SEQUENCE { * CHOICE diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java index 024e14834..c31aabb4c 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPublicKey.java @@ -14,7 +14,6 @@ import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil; /** * This class implements an ASN.1 encoded Rainbow public key. The ASN.1 definition * of this structure is: - * ** RainbowPublicKey ::= SEQUENCE { * CHOICE diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java index a67d30fcd..bb1ef36dd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSKeyPairGenerator.java @@ -98,7 +98,6 @@ public class GMSSKeyPairGenerator /** * The standard constructor tries to generate the GMSS algorithm identifier * with the corresponding OID. - * * * @param digestProvider provider for digest implementations. */ @@ -363,21 +362,21 @@ public class GMSSKeyPairGenerator * This method initializes the GMSS KeyPairGenerator using an integer value *keySize
as input. It provides a simple use of the GMSS for * testing demands. - * + ** A given
* * @param layers the number of authentication tree layers * @param heightOfTrees the height of the authentication trees diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java index 0bb04fa0c..2a78d385a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSSigner.java @@ -214,7 +214,6 @@ public class GMSSSigner /** * Signs a message. - * * * @return the signature. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java index f971a8bd6..0a1e52eb0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSVerify.java @@ -20,7 +20,6 @@ public class WinternitzOTSVerify /** * The constructor - * * * @param digest the name of the hash function used by the OTS and the provider * name of the hash function diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java index 92fa23dd0..2ec2c1ad3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/util/WinternitzOTSignature.java @@ -50,7 +50,6 @@ public class WinternitzOTSignature /** * The constructor generates an OTS key pair, usingkeysize
of less than 10 creates an amount 2^10 * signatures. A keySize between 10 and 20 creates 2^20 signatures. Given an * integer greater than 20 the key pair generator creates 2^40 signatures. * * @param keySize Assigns the parameters used for the GMSS signatures. There are - * 3 choices:
- * 1. keysize <= 10: creates 2^10 signatures using the - * parameterset
- * P = (2, (5, 5), (3, 3), (3, 3))
- * 2. keysize > 10 and <= 20: creates 2^20 signatures using the - * parameterset
- * P = (2, (10, 10), (5, 4), (2, 2))
- * 3. keysize > 20: creates 2^40 signatures using the - * parameterset
+ * 3 choices:
+ * 1. keysize <= 10: creates 2^10 signatures using the + * parameterset
+ * P = (2, (5, 5), (3, 3), (3, 3))
+ * 2. keysize > 10 and <= 20: creates 2^20 signatures using the + * parameterset
+ * P = (2, (10, 10), (5, 4), (2, 2))
+ * 3. keysize > 20: creates 2^40 signatures using the + * parameterset
* P = (2, (10, 10, 10, 10), (9, 9, 9, 3), (2, 2, 2, 2)) * @param secureRandom not used by GMSS, the SHA1PRNG of the SUN Provider is always * used diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java index ffc5043e5..c78d50e3e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/gmss/GMSSParameters.java @@ -32,7 +32,6 @@ public class GMSSParameters /** * The constructor for the parameters of the GMSSKeyPairGenerator. - *seed0
and * the PRNG - * * * @param seed0 the seed for the PRGN * @param digest an array of strings, containing the name of the used hash diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java index ce9d813f9..76cb839d4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyGenerationParameters.java @@ -79,7 +79,7 @@ public class NTRUEncryptionKeyGenerationParameters public Digest hashAlg; /** - * Constructs a parameter set that uses ternary private keys (i.e. polyType=SIMPLE). + * Constructs a parameter set that uses ternary private keys (i.e.polyType=SIMPLE
). * * @param N number of polynomial coefficients * @param q modulus @@ -116,7 +116,7 @@ public class NTRUEncryptionKeyGenerationParameters } /** - * Constructs a parameter set that uses product-form private keys (i.e. polyType=PRODUCT). + * Constructs a parameter set that uses product-form private keys (i.e.polyType=PRODUCT
). * * @param N number of polynomial coefficients * @param q modulus diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java index bf63c33f0..fd483f090 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionKeyPairGenerator.java @@ -10,7 +10,7 @@ import org.spongycastle.pqc.math.ntru.polynomial.ProductFormPolynomial; import org.spongycastle.pqc.math.ntru.util.Util; /** - * Generates key pairs.
+ * Generates key pairs.
* The parameter p is hardcoded to 3. */ public class NTRUEncryptionKeyPairGenerator diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java index 8f5f9a9b6..86dabae81 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionParameters.java @@ -42,7 +42,7 @@ public class NTRUEncryptionParameters public Digest hashAlg; /** - * Constructs a parameter set that uses ternary private keys (i.e. polyType=SIMPLE). + * Constructs a parameter set that uses ternary private keys (i.e.polyType=SIMPLE
). * * @param N number of polynomial coefficients * @param q modulus @@ -78,7 +78,7 @@ public class NTRUEncryptionParameters } /** - * Constructs a parameter set that uses product-form private keys (i.e. polyType=PRODUCT). + * Constructs a parameter set that uses product-form private keys (i.e.polyType=PRODUCT
). * * @param N number of polynomial coefficients * @param q modulus diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java index 9fe8259f3..5b0adbea8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEncryptionPrivateKeyParameters.java @@ -14,7 +14,7 @@ import org.spongycastle.pqc.math.ntru.polynomial.SparseTernaryPolynomial; /** * A NtruEncrypt private key is essentially a polynomial namedf
* which takes different forms depending on whether product-form polynomials are used, - * and onfastP
+ * and onfastP
* The inverse off
modulop
is precomputed on initialization. */ public class NTRUEncryptionPrivateKeyParameters diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java index ff7746204..571057e27 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUEngine.java @@ -17,7 +17,7 @@ import org.spongycastle.pqc.math.ntru.polynomial.TernaryPolynomial; import org.spongycastle.util.Arrays; /** - * Encrypts, decrypts data and generates key pairs.
+ * Encrypts, decrypts data and generates key pairs.
* The parameter p is hardcoded to 3. */ public class NTRUEngine diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java index 2dc19773a..0886cff1a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigner.java @@ -8,8 +8,12 @@ import org.spongycastle.pqc.math.ntru.polynomial.IntegerPolynomial; import org.spongycastle.pqc.math.ntru.polynomial.Polynomial; /** - * Signs, verifies data and generates key pairs. - */ +* Signs, verifies data and generates key pairs. +* @deprecated the NTRUSigner algorithm was broken in 2012 by Ducas and Nguyen. See +* +* http://www.di.ens.fr/~ducas/NTRUSign_Cryptanalysis/DucasNguyen_Learning.pdf +* for details. +*/ public class NTRUSigner { private NTRUSigningParameters params; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java index 2f6eaab55..f9c17f1c0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningKeyGenerationParameters.java @@ -29,22 +29,22 @@ public class NTRUSigningKeyGenerationParameters /** * Gives 128 bits of security */ - public static final NTRUSigningKeyGenerationParameters APR2011_439 = new NTRUSigningKeyGenerationParameters(439, 2048, 146, 1, BASIS_TYPE_TRANSPOSE, 0.165, 400, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest()); + public static final NTRUSigningKeyGenerationParameters APR2011_439 = new NTRUSigningKeyGenerationParameters(439, 2048, 146, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest()); /** * LikeAPR2011_439
, this parameter set gives 128 bits of security but uses product-form polynomials */ - public static final NTRUSigningKeyGenerationParameters APR2011_439_PROD = new NTRUSigningKeyGenerationParameters(439, 2048, 9, 8, 5, 1, BASIS_TYPE_TRANSPOSE, 0.165, 400, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest()); + public static final NTRUSigningKeyGenerationParameters APR2011_439_PROD = new NTRUSigningKeyGenerationParameters(439, 2048, 9, 8, 5, 1, BASIS_TYPE_TRANSPOSE, 0.165, 490, 280, false, true, KEY_GEN_ALG_RESULTANT, new SHA256Digest()); /** * Gives 256 bits of security */ - public static final NTRUSigningKeyGenerationParameters APR2011_743 = new NTRUSigningKeyGenerationParameters(743, 2048, 248, 1, BASIS_TYPE_TRANSPOSE, 0.127, 405, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest()); + public static final NTRUSigningKeyGenerationParameters APR2011_743 = new NTRUSigningKeyGenerationParameters(743, 2048, 248, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest()); /** * LikeAPR2011_439
, this parameter set gives 256 bits of security but uses product-form polynomials */ - public static final NTRUSigningKeyGenerationParameters APR2011_743_PROD = new NTRUSigningKeyGenerationParameters(743, 2048, 11, 11, 15, 1, BASIS_TYPE_TRANSPOSE, 0.127, 405, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest()); + public static final NTRUSigningKeyGenerationParameters APR2011_743_PROD = new NTRUSigningKeyGenerationParameters(743, 2048, 11, 11, 15, 1, BASIS_TYPE_TRANSPOSE, 0.127, 560, 360, true, false, KEY_GEN_ALG_RESULTANT, new SHA512Digest()); /** * Generates key pairs quickly. Use for testing only. @@ -75,7 +75,7 @@ public class NTRUSigningKeyGenerationParameters public int polyType; /** - * Constructs a parameter set that uses ternary private keys (i.e. polyType=SIMPLE). + * Constructs a parameter set that uses ternary private keys (i.e.polyType=SIMPLE
). * * @param N number of polynomial coefficients * @param q modulus @@ -110,7 +110,7 @@ public class NTRUSigningKeyGenerationParameters } /** - * Constructs a parameter set that uses product-form private keys (i.e. polyType=PRODUCT). + * Constructs a parameter set that uses product-form private keys (i.e.polyType=PRODUCT
). * * @param N number of polynomial coefficients * @param q modulus diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java index 44c5a0a1e..bf9ba2cb9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/ntru/NTRUSigningParameters.java @@ -29,7 +29,7 @@ public class NTRUSigningParameters public Digest hashAlg; /** - * Constructs a parameter set that uses ternary private keys (i.e. polyType=SIMPLE). + * Constructs a parameter set that uses ternary private keys (i.e.polyType=SIMPLE
). * * @param N number of polynomial coefficients * @param q modulus @@ -52,7 +52,7 @@ public class NTRUSigningParameters } /** - * Constructs a parameter set that uses product-form private keys (i.e. polyType=PRODUCT). + * Constructs a parameter set that uses product-form private keys (i.e.polyType=PRODUCT
). * * @param N number of polynomial coefficients * @param q modulus diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java index 73eaaf118..0556531e9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/Layer.java @@ -10,14 +10,14 @@ import org.spongycastle.util.Arrays; /** * This class represents a layer of the Rainbow Oil- and Vinegar Map. Each Layer * consists of oi polynomials with their coefficients, generated at random. - * + ** To sign a document, we solve a LES (linear equation system) for each layer in * order to find the oil variables of that layer and to be able to use the * variables to compute the signature. This functionality is implemented in the * RainbowSignature-class, by the aid of the private key. - *
+ ** Each layer is a part of the private key. - *
+ ** More information about the layer can be found in the paper of Jintai Ding, * Dieter Schmidt: Rainbow, a New Multivariable Polynomial Signature Scheme. * ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12) @@ -124,7 +124,7 @@ public class Layer * This method plugs in the vinegar variables into the polynomials of this * layer and computes the coefficients of the Oil-variables as well as the * free coefficient in each polynomial. - *
+ ** It is needed for computing the Oil variables while signing. * * @param x vinegar variables of this layer that should be plugged into diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java index ac9a1ae78..1115d649f 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowKeyPairGenerator.java @@ -12,7 +12,7 @@ import org.spongycastle.pqc.crypto.rainbow.util.GF2Field; * This class implements AsymmetricCipherKeyPairGenerator. It is used * as a generator for the private and public key of the Rainbow Signature * Scheme. - *
+ ** Detailed information about the key generation is to be found in the paper of * Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable Polynomial * Signature Scheme. ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12) @@ -49,7 +49,6 @@ public class RainbowKeyPairGenerator /** * The standard constructor tries to generate the Rainbow algorithm identifier * with the corresponding OID. - *
*/ public RainbowKeyPairGenerator() { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java index 12bd9810b..9033b37e8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/RainbowSigner.java @@ -12,7 +12,7 @@ import org.spongycastle.pqc.crypto.rainbow.util.GF2Field; * It implements the sign and verify functions for the Rainbow Signature Scheme. * Here the message, which has to be signed, is updated. The use of * different hash functions is possible. - * + ** Detailed information about the signature and the verify-method is to be found * in the paper of Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable * Polynomial Signature Scheme. ACNS 2005: 164-175 @@ -96,10 +96,10 @@ public class RainbowSigner /** * This function signs the message that has been updated, making use of the * private key. - *
+ ** For computing the signature, L1 and L2 are needed, as well as LES should * be solved for each layer in order to find the Oil-variables in the layer. - *
+ ** The Vinegar-variables of the first layer are random generated. * * @param message the message diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java index 2094fb031..1e4b6c0f8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/ComputeInField.java @@ -2,7 +2,7 @@ package org.spongycastle.pqc.crypto.rainbow.util; /** * This class offers different operations on matrices in field GF2^8. - *
+ ** Implemented are functions: * - finding inverse of a matrix * - solving linear equation systems using the Gauss-Elimination method @@ -88,7 +88,7 @@ public class ComputeInField /** * This function computes the inverse of a given matrix using the Gauss- * Elimination method. - *
+ ** An exception is thrown if the matrix has no inverse * * @param coef the matrix which inverse matrix is needed @@ -345,7 +345,7 @@ public class ComputeInField /** * This function multiplies a given matrix with a one-dimensional array. - *
+ ** An exception is thrown, if the number of columns in the matrix and * the number of rows in the one-dim. array differ. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java index 19b47a2fd..675f0ec52 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/crypto/rainbow/util/GF2Field.java @@ -3,10 +3,10 @@ package org.spongycastle.pqc.crypto.rainbow.util; /** * This class provides the basic operations like addition, multiplication and * finding the multiplicative inverse of an element in GF2^8. - *
+ ** The operations are implemented using the irreducible polynomial * 1+x^2+x^3+x^6+x^8 ( 1 0100 1101 = 0x14d ) - *
+ ** This class makes use of lookup tables(exps and logs) for implementing the * operations in order to increase the efficiency of Rainbow. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java index fdef21054..25bf099ab 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2Polynomial.java @@ -1339,7 +1339,7 @@ public class GF2Polynomial /** * Checks if this is irreducible, according to IEEE P1363, A.5.5, - * p103.
+ *
+ * p103.
* Note: The algorithm from IEEE P1363, A5.5 can be used to check a * polynomial with coefficients in GF(2^r) for irreducibility. As this class * only represents polynomials with coefficients in GF(2), the algorithm is @@ -1635,7 +1635,7 @@ public class GF2Polynomial * Does a vector-multiplication modulo 2 and returns the result as boolean. * * @param b GF2Polynomial - * @return this x b as boolean (1->true, 0->false) + * @return this x b as boolean (1->true, 0->false) * @throws PolynomialsHaveDifferentLengthException if this and b have a different length and * thus cannot be vector-multiplied */ @@ -1730,7 +1730,7 @@ public class GF2Polynomial * Sets the bit at position i. * * @param i int - * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) + * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) */ public void setBit(int i) throws RuntimeException @@ -1767,7 +1767,7 @@ public class GF2Polynomial * Resets the bit at position i. * * @param i int - * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) + * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) */ public void resetBit(int i) throws RuntimeException @@ -1787,7 +1787,7 @@ public class GF2Polynomial * Xors the bit at position i. * * @param i int - * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) + * @throws BitDoesNotExistException if (i < 0) || (i > (len - 1)) */ public void xorBit(int i) throws RuntimeException @@ -1808,7 +1808,7 @@ public class GF2Polynomial * * @param i the position of the bit to be tested * @return true if the bit at position i is set (a(i) == - * 1). False if (i < 0) || (i > (len - 1)) + * 1). False if (i < 0) || (i > (len - 1)) */ public boolean testBit(int i) { @@ -1822,7 +1822,7 @@ public class GF2Polynomial /** * Returns this GF2Polynomial shift-left by 1 in a new GF2Polynomial. * - * @return a new GF2Polynomial (this << 1) + * @return a new GF2Polynomial (this << 1) */ public GF2Polynomial shiftLeft() { @@ -1878,7 +1878,7 @@ public class GF2Polynomial * GF2Polynomial. * * @param k int - * @return a new GF2Polynomial (this << k) + * @return a new GF2Polynomial (this << k) */ public GF2Polynomial shiftLeft(int k) { @@ -1996,7 +1996,7 @@ public class GF2Polynomial /** * Returns this GF2Polynomial shift-right by 1 in a new GF2Polynomial. * - * @return a new GF2Polynomial (this << 1) + * @return a new GF2Polynomial (this << 1) */ public GF2Polynomial shiftRight() { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java index 5e7fa734c..b60cd5982 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mField.java @@ -7,9 +7,9 @@ import java.security.SecureRandom; * GF(2^m). ( GF(2^m)= GF(2)[A] where A is a root of irreducible polynomial with * degree m, each field element B has a polynomial basis representation, i.e. it * is represented by a different binary polynomial of degree less than m, B = - * poly(A) ) All operations are defined only for field with 1< m <32. For the - * representation of field elements the map f: F->Z, poly(A)->poly(2) is used, - * where integers have the binary representation. For example: A^7+A^3+A+1 -> + * poly(A) ) All operations are defined only for field with 1< m <32. For the + * representation of field elements the map f: F->Z, poly(A)->poly(2) is used, + * where integers have the binary representation. For example: A^7+A^3+A+1 -> * (00...0010001011)=139 Also for elements type Integer is used. * * @see PolynomialRingGF2 @@ -291,7 +291,7 @@ public class GF2mField /** * checks if given object is equal to this field. - ** The method returns false whenever the given object is not GF2m. * * @param other object @@ -322,7 +322,6 @@ public class GF2mField /** * Returns a human readable form of this field. - *
* * @return a human readable form of this field. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java index fb2b1e4b8..d2989bcfd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mMatrix.java @@ -2,7 +2,7 @@ package org.spongycastle.pqc.math.linearalgebra; /** * This class describes some operations with matrices over finite field GF(2m) - * with small m (1< m <32). + * with small m (1< m <32). * * @see Matrix */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java index b576ef632..8e613e7bd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2mVector.java @@ -161,7 +161,7 @@ public class GF2mVector * @return this + addend * @throws ArithmeticException if the other vector is not defined over the same field as * this vector. - * + ** TODO: implement this method */ public Vector add(Vector addend) diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java index 08d5beed7..b14fdd1a9 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/GF2nONBElement.java @@ -1048,7 +1048,7 @@ public class GF2nONBElement /** * Returns a String representation of this element. radix * specifies the radix of the String representation.
- * + *
- * NOTE: ONLY radix = 2 or radix = 16 IS IMPLEMENTED> + * NOTE: ONLY radix = 2 or radix = 16 IS IMPLEMENTED * * @param radix specifies the radix of the String representation * @return String representation of this element with the specified radix diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java index f031abf05..e586666e3 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntUtils.java @@ -70,8 +70,7 @@ public final class IntUtils * Sorts this array of integers according to the Quicksort algorithm. After * calling this method this array is sorted in ascending order with the * smallest integer taking position 0 in the array. - ** This implementation is based on the quicksort algorithm as described in *
- * (A|B) = 0 IF gcd(A,B) > 1Data Structures In Java
by Thomas A. Standish, Chapter 10, * ISBN 0-201-30564-X. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java index ca004311b..a6d5a1817 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/IntegerFunctions.java @@ -38,8 +38,8 @@ public final class IntegerFunctions * Computes the value of the Jacobi symbol (A|B). The following properties * hold for the Jacobi symbol which makes it a very efficient way to * evaluate the Legendre symbol - *
+ *+ * (A|B) = 0 IF gcd(A,B) > 1
* * @param A integer value * @param B integer value @@ -493,10 +492,10 @@ public final class IntegerFunctions } /** - * determines the order of g modulo p, p prime and 1 < g < p. This algorithm + * determines the order of g modulo p, p prime and 1 < g < p. This algorithm * is only efficient for small p (see X9.62-1998, p. 68). * - * @param g an integer with 1 < g < p + * @param g an integer with 1 < g < p * @param p a prime * @return the order k of g (that is k is the smallest integer with * gk = 1 mod p @@ -743,7 +742,7 @@ public final class IntegerFunctions * Find and return the least non-trivial divisor of an integer a. * * @param a - the integer - * @return divisor p >1 or 1 if a = -1,0,1 + * @return divisor p >1 or 1 if a = -1,0,1 */ public static int leastDiv(int a) { @@ -1008,11 +1007,11 @@ public final class IntegerFunctions } /** - * Computes the binomial coefficient (n|t) ("n over t"). Formula:
* (-1|B) = 1 IF n = 1 (mod 1)
* (-1|B) = -1 IF n = 3 (mod 4)
* (A|B) (C|B) = (AC|B)
@@ -47,7 +47,6 @@ public final class IntegerFunctions * (A|B) = (C|B) IF A = C (mod B)
* (2|B) = 1 IF N = 1 OR 7 (mod 8)
* (2|B) = 1 IF N = 3 OR 5 (mod 8) - *
+ * Computes the binomial coefficient (n|t) ("n over t"). Formula: **
* * @param n - the "upper" integer @@ -1225,7 +1224,7 @@ public final class IntegerFunctions /** * calculate the logarithm to the base 2. * - * @param x any long value >=1 + * @param x any long value >=1 * @return log_2(x) * @deprecated use MathFunctions.log(long) instead */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java index 2f1b505b3..d156672fb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/Permutation.java @@ -179,7 +179,7 @@ public class Permutation /** * checks if given object is equal to this permutation. - * + *- if n !=0 and t != 0 then (n|t) = Mult(i=1, t): (n-(i-1))/i
*- if t = 0 then (n|t) = 1
- *- if n = 0 and t > 0 then (n|t) = 0
+ *- if n = 0 and t > 0 then (n|t) = 0
** The method returns false whenever the given object is not permutation. * * @param other - diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java index adab34ccd..6426a4cec 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialGF2mSmallM.java @@ -4,7 +4,7 @@ import java.security.SecureRandom; /** * This class describes operations with polynomials from the ring R = - * GF(2^m)[X], where 2 <= m <=31. + * GF(2^m)[X], where 2 <= m <=31. * * @see GF2mField * @see PolynomialRingGF2m @@ -948,10 +948,10 @@ public class PolynomialGF2mSmallM /** * Compute a polynomial pair (a,b) from this polynomial and the given - * polynomial g with the property b*this = a mod g and deg(a)<=deg(g)/2. + * polynomial g with the property b*this = a mod g and deg(a)<=deg(g)/2. * * @param g the reduction polynomial - * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<= + * @return PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<= * deg(g)/2 */ public PolynomialGF2mSmallM[] modPolynomialToFracton(PolynomialGF2mSmallM g) @@ -978,7 +978,7 @@ public class PolynomialGF2mSmallM /** * checks if given object is equal to this polynomial. - *
+ ** The method returns false whenever the given object is not polynomial over * GF(2^m). * @@ -1045,7 +1045,6 @@ public class PolynomialGF2mSmallM /** * Returns a human readable form of the polynomial. - *
* * @return a human readable form of the polynomial. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java index 1dbb320f7..850b5dbfd 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2.java @@ -3,9 +3,9 @@ package org.spongycastle.pqc.math.linearalgebra; /** * This class describes operations with polynomials over finite field GF(2), i e * polynomial ring R = GF(2)[X]. All operations are defined only for polynomials - * with degree <=32. For the polynomial representation the map f: R->Z, - * poly(X)->poly(2) is used, where integers have the binary representation. For - * example: X^7+X^3+X+1 -> (00...0010001011)=139 Also for polynomials type + * with degree <=32. For the polynomial representation the map f: R->Z, + * poly(X)->poly(2) is used, where integers have the binary representation. For + * example: X^7+X^3+X+1 -> (00...0010001011)=139 Also for polynomials type * Integer is used. * * @see GF2mField diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java index efa7ce8ac..7700fe52d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/linearalgebra/PolynomialRingGF2m.java @@ -2,7 +2,7 @@ package org.spongycastle.pqc.math.linearalgebra; /** * This class represents polynomial rings GF(2^m)[X]/p(X) for - * m<<;32. If p(X) is irreducible, the polynomial ring + * m<32. If p(X) is irreducible, the polynomial ring * is in fact an extension field of GF(2^m). */ public class PolynomialRingGF2m diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java index eec9ebf79..e48d2a0ce 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/BigIntEuclidean.java @@ -14,7 +14,7 @@ public class BigIntEuclidean } /** - * Runs the EEA on twoBigInteger
s
+ * Runs the EEA on twoBigInteger
s
* Implemented from pseudocode on Wikipedia. * * @param a diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java index 185fcc709..0791b01e7 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/euclid/IntEuclidean.java @@ -12,7 +12,7 @@ public class IntEuclidean } /** - * Runs the EEA on twoint
s
+ * Runs the EEA on twoint
s
* Implemented from pseudocode on Wikipedia. * * @param a diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java index ceb8a6071..2869fec87 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/BigIntPolynomial.java @@ -10,7 +10,7 @@ import java.util.List; import org.spongycastle.util.Arrays; /** - * A polynomial with {@link BigInteger} coefficients.
+ * A polynomial with {@link BigInteger} coefficients.
* Some methods (likeadd
) change the polynomial, others (likemult
) do * not but return the result as a new polynomial. */ @@ -95,7 +95,7 @@ public class BigIntPolynomial /** * Multiplies the polynomial by another, taking the indices mod N. Does not - * change this polynomial but returns the result as a new polynomial.
+ * change this polynomial but returns the result as a new polynomial.
* Both polynomials must have the same number of coefficients. * * @param poly2 the polynomial to multiply by @@ -257,7 +257,7 @@ public class BigIntPolynomial } /** - * Divides each coefficient by aBigInteger
and rounds the result to the nearest whole number.
+ * Divides each coefficient by aBigInteger
and rounds the result to the nearest whole number.
* Does not return a new polynomial but modifies this polynomial. * * @param divisor the number to divide by diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java index 9605b4c91..41e921bff 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/IntegerPolynomial.java @@ -19,7 +19,7 @@ import org.spongycastle.pqc.math.ntru.util.Util; import org.spongycastle.util.Arrays; /** - * A polynomial withint
coefficients.
+ * A polynomial withint
coefficients.
* Some methods (likeadd
) change the polynomial, others (likemult
) do * not but return the result as a new polynomial. */ @@ -143,7 +143,7 @@ public class IntegerPolynomial } /** - * Decodes a byte array to a polynomial withN
ternary coefficients
+ * Decodes a byte array to a polynomial withN
ternary coefficients
* Ignores any excess bytes. * * @param data an encoded ternary polynomial @@ -181,8 +181,8 @@ public class IntegerPolynomial } /** - * Returns a polynomial with N coefficients between0
andq-1
.
- *q
must be a power of 2.
+ * Returns a polynomial with N coefficients between0
andq-1
.
+ *q
must be a power of 2.
* Ignores any excess bytes. * * @param data an encoded ternary polynomial @@ -196,8 +196,8 @@ public class IntegerPolynomial } /** - * Returns a polynomial with N coefficients between0
andq-1
.
- *q
must be a power of 2.
+ * Returns a polynomial with N coefficients between0
andq-1
.
+ *q
must be a power of 2.
* Ignores any excess bytes. * * @param is an encoded ternary polynomial @@ -213,7 +213,7 @@ public class IntegerPolynomial /** * Encodes a polynomial with ternary coefficients to binary. - *coeffs[2*i]
andcoeffs[2*i+1]
must not both equal -1 for any integer i, + *
icoeffs[2*i]
andcoeffs[2*i+1]
must not both equal -1 for any integeri
, * so this method is only safe to use with polynomials produced byfromBinary3Sves()
. * * @return the encoded polynomial @@ -366,7 +366,7 @@ public class IntegerPolynomial } /** - * Computes the inverse modq; q
must be a power of 2.
+ * Computes the inverse modq; q
must be a power of 2.
* Returnsnull
if the polynomial is not invertible. * * @param q the modulus @@ -572,14 +572,14 @@ public class IntegerPolynomial /** * Resultant of this polynomial withx^n-1
using a probabilistic algorithm. - * + ** Unlike EESS, this implementation does not compute all resultants modulo primes * such that their product exceeds the maximum possible resultant, but rather stops - * when
+ *NUM_EQUAL_RESULTANTS
consecutive modular resultants are equal.
+ * whenNUM_EQUAL_RESULTANTS
consecutive modular resultants are equal.
* This means the return value may be incorrect. Experiments show this happens in * about 1 out of 100 cases whenN=439
andNUM_EQUAL_RESULTANTS=2
, * so the likelyhood of leaving the loop too early is(1/100)^(NUM_EQUAL_RESULTANTS-1)
. - ** Because of the above, callers must verify the output and try a different polynomial if necessary. * * @return
(rho, res)
satisfyingres = rho*this + t*(x^n-1)
for some integert
. @@ -766,7 +766,7 @@ public class IntegerPolynomial } /** - * Resultant of this polynomial withx^n-1 mod p
.
+ * Resultant of this polynomial withx^n-1 mod p
. * * @return(rho, res)
satisfyingres = rho*this + t*(x^n-1) mod p
for some integert
. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java index be8001b51..513cac504 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial2.java @@ -4,7 +4,7 @@ import org.spongycastle.util.Arrays; /** * A polynomial class that combines two coefficients into onelong
value for - * faster multiplication in 64 bit environments.
+ * faster multiplication in 64 bit environments.
* Coefficients can be between 0 and 2047 and are stored in pairs in the bits 0..10 and 24..34 of along
number. */ public class LongPolynomial2 diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java index 6524f9ff3..f8764c680 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/LongPolynomial5.java @@ -4,7 +4,7 @@ import org.spongycastle.util.Arrays; /** * A polynomial class that combines five coefficients into onelong
value for - * faster multiplication by a ternary polynomial.
+ * faster multiplication by a ternary polynomial.
* Coefficients can be between 0 and 2047 and are stored in bits 0..11, 12..23, ..., 48..59 of along
number. */ public class LongPolynomial5 diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java index 588163414..1d1f1dfbc 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/polynomial/Polynomial.java @@ -32,7 +32,7 @@ public interface Polynomial /** * Multiplies the polynomial by aBigIntPolynomial
, taking the indices mod N. Does not - * change this polynomial but returns the result as a new polynomial.
+ * change this polynomial but returns the result as a new polynomial.
* Both polynomials must have the same number of coefficients. * * @param poly2 the polynomial to multiply by diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java index 8c9e3e034..c4888cfc8 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/pqc/math/ntru/util/ArrayEncoder.java @@ -56,7 +56,7 @@ public class ArrayEncoder /** * Encodes an int array whose elements are between 0 andq
, - * to a byte array leaving no gaps between bits.
+ * to a byte array leaving no gaps between bits.
*q
must be a power of 2. * * @param a the input array @@ -92,8 +92,8 @@ public class ArrayEncoder } /** - * Decodes abyte
array encoded with {@link #encodeModQ(int[], int)} back to anint
array.
- *N
is the number of coefficients.q
must be a power of2
.
+ * Decodes abyte
array encoded with {@link #encodeModQ(int[], int)} back to anint
array.
+ *N
is the number of coefficients.q
must be a power of2
.
* Ignores any excess bytes. * * @param data an encoded ternary polynomial @@ -120,8 +120,8 @@ public class ArrayEncoder } /** - * Decodes data encoded with {@link #encodeModQ(int[], int)} back to anint
array.
- *N
is the number of coefficients.q
must be a power of2
.
+ * Decodes data encoded with {@link #encodeModQ(int[], int)} back to anint
array.
+ *N
is the number of coefficients.q
must be a power of2
.
* Ignores any excess bytes. * * @param is an encoded ternary polynomial @@ -140,8 +140,8 @@ public class ArrayEncoder /** * Decodes abyte
array encoded with {@link #encodeMod3Sves(int[])} back to anint
array - * withN
coefficients between-1
and1
.
- * Ignores any excess bytes.
+ * withN
coefficients between-1
and1
.
+ * Ignores any excess bytes.
* See P1363.1 section 9.2.2. * * @param data an encoded ternary polynomial @@ -171,8 +171,8 @@ public class ArrayEncoder /** * Encodes anint
array whose elements are between-1
and1
, to a byte array. - *coeffs[2*i]
andcoeffs[2*i+1]
must not both equal -1 for any integer, - * so this method is only safe to use with arrays produced by {@link #decodeMod3Sves(byte[], int)}.
+ *coeffs[2*i]
andcoeffs[2*i+1]
must not both equal -1 for any integeri
, + * so this method is only safe to use with arrays produced by {@link #decodeMod3Sves(byte[], int)}.
* See P1363.1 section 9.2.3. * * @param arr diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Arrays.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Arrays.java index 05bb3e12e..a847f7210 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Arrays.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Arrays.java @@ -323,6 +323,25 @@ public final class Arrays return hc; } + + public static int hashCode(byte[] data, int off, int len) + { + if (data == null) + { + return 0; + } + + int i = len; + int hc = i + 1; + + while (--i >= 0) + { + hc *= 257; + hc ^= data[off + i]; + } + + return hc; + } public static int hashCode(char[] data) { @@ -374,6 +393,25 @@ public final class Arrays return hc; } + public static int hashCode(int[] data, int off, int len) + { + if (data == null) + { + return 0; + } + + int i = len; + int hc = i + 1; + + while (--i >= 0) + { + hc *= 257; + hc ^= data[off + i]; + } + + return hc; + } + public static int hashCode(short[][][] shorts) { int hc = 0; @@ -752,6 +790,20 @@ public final class Arrays return result; } + public static short[] append(short[] a, short b) + { + if (a == null) + { + return new short[]{ b }; + } + + int length = a.length; + short[] result = new short[length + 1]; + System.arraycopy(a, 0, result, 0, length); + result[length] = b; + return result; + } + public static int[] append(int[] a, int b) { if (a == null) @@ -840,6 +892,23 @@ public final class Arrays } } + public static int[] concatenate(int[] a, int[] b) + { + if (a == null) + { + return clone(b); + } + if (b == null) + { + return clone(a); + } + + int[] c = new int[a.length + b.length]; + System.arraycopy(a, 0, c, 0, a.length); + System.arraycopy(b, 0, c, a.length, b.length); + return c; + } + public static byte[] prepend(byte[] a, byte b) { if (a == null) @@ -853,4 +922,50 @@ public final class Arrays result[0] = b; return result; } + + public static short[] prepend(short[] a, short b) + { + if (a == null) + { + return new short[]{ b }; + } + + int length = a.length; + short[] result = new short[length + 1]; + System.arraycopy(a, 0, result, 1, length); + result[0] = b; + return result; + } + + public static int[] prepend(int[] a, int b) + { + if (a == null) + { + return new int[]{ b }; + } + + int length = a.length; + int[] result = new int[length + 1]; + System.arraycopy(a, 0, result, 1, length); + result[0] = b; + return result; + } + + public static byte[] reverse(byte[] a) + { + if (a == null) + { + return null; + } + + int p1 = 0, p2 = a.length; + byte[] result = new byte[p2]; + + while (--p2 >= 0) + { + result[p2] = a[p1++]; + } + + return result; + } } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Integers.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Integers.java index adfa69501..e212c9fc0 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Integers.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Integers.java @@ -2,6 +2,16 @@ package org.spongycastle.util; public class Integers { + public static int rotateLeft(int i, int distance) + { + return Integer.rotateLeft(i, distance); + } + + public static int rotateRight(int i, int distance) + { + return Integer.rotateRight(i, distance); + } + public static Integer valueOf(int value) { return Integer.valueOf(value); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Memoable.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Memoable.java index 75280e5a2..5680c857e 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Memoable.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Memoable.java @@ -4,7 +4,7 @@ public interface Memoable { /** * Produce a copy of this object with its configuration and in its current state. - * + ** The returned object may be used simply to store the state, or may be used as a similar object * starting from the copied state. */ @@ -12,7 +12,7 @@ public interface Memoable /** * Restore a copied object state into this object. - *
+ ** Implementations of this method should try to avoid or minimise memory allocation to perform the reset. * * @param other an object originally {@link #copy() copied} from an object of the same type as this instance. diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Pack.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Pack.java new file mode 100644 index 000000000..bad72850c --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Pack.java @@ -0,0 +1,201 @@ +package org.spongycastle.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 void littleEndianToInt(byte[] bs, int bOff, int[] ns, int nOff, int count) + { + for (int i = 0; i < count; ++i) + { + ns[nOff + i] = littleEndianToInt(bs, bOff); + bOff += 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/extern/spongycastle/core/src/main/java/org/spongycastle/util/Strings.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Strings.java index 6657ed394..7e2694556 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Strings.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Strings.java @@ -241,6 +241,17 @@ public final class Strings return bytes; } + public static int toByteArray(String s, byte[] buf, int off) + { + int count = s.length(); + for (int i = 0; i < count; ++i) + { + char c = s.charAt(i); + buf[off + i] = (byte)c; + } + return count; + } + /** * Convert an array of 8 bit characters into a string. * diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/Times.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Times.java new file mode 100644 index 000000000..71d49e31d --- /dev/null +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/Times.java @@ -0,0 +1,9 @@ +package org.spongycastle.util; + +public final class Times +{ + public static long nanoTime() + { + return System.nanoTime(); + } +} diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64.java index 8060acbdd..a2b5aff89 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64.java @@ -6,6 +6,9 @@ import java.io.OutputStream; import org.spongycastle.util.Strings; +/** + * Utility class for converting Base64 data to bytes and back again. + */ public class Base64 { private static final Encoder encoder = new Base64Encoder(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java index e207e2e4e..17bae1dda 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Base64Encoder.java @@ -3,24 +3,27 @@ package org.spongycastle.util.encoders; import java.io.IOException; import java.io.OutputStream; +/** + * A streaming Base64 encoder. + */ public class Base64Encoder implements Encoder { protected final byte[] encodingTable = - { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', - (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', - (byte)'7', (byte)'8', (byte)'9', - (byte)'+', (byte)'/' - }; + { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', + (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', + (byte)'7', (byte)'8', (byte)'9', + (byte)'+', (byte)'/' + }; protected byte padding = (byte)'='; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java index cc8cb27b1..31c702aee 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedDecoder.java @@ -2,7 +2,7 @@ package org.spongycastle.util.encoders; /** - * a buffering class to allow translation from one format to another to + * A buffering class to allow translation from one format to another to * be done in discrete chunks. */ public class BufferedDecoder diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java index 3dc41c0e2..fbeb92b63 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/BufferedEncoder.java @@ -2,7 +2,7 @@ package org.spongycastle.util.encoders; /** - * a buffering class to allow translation from one format to another to + * A buffering class to allow translation from one format to another to * be done in discrete chunks. */ public class BufferedEncoder diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java index cdaa31564..88e0b7c0a 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/DecoderException.java @@ -1,5 +1,8 @@ package org.spongycastle.util.encoders; +/** + * Exception thrown if an attempt is made to decode invalid data, or some other failure occurs. + */ public class DecoderException extends IllegalStateException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java index c7b233132..936fce021 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/EncoderException.java @@ -1,5 +1,8 @@ package org.spongycastle.util.encoders; +/** + * Exception thrown if an attempt is made to encode invalid data, or some other failure occurs. + */ public class EncoderException extends IllegalStateException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Hex.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Hex.java index 920b2d627..5d0efc138 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Hex.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Hex.java @@ -6,6 +6,9 @@ import java.io.OutputStream; import org.spongycastle.util.Strings; +/** + * Utility class for converting hex data to bytes and back again. + */ public class Hex { private static final Encoder encoder = new HexEncoder(); diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java index 609123729..161201291 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/HexEncoder.java @@ -3,15 +3,18 @@ package org.spongycastle.util.encoders; import java.io.IOException; import java.io.OutputStream; +/** + * A streaming Hex encoder. + */ public class HexEncoder implements Encoder { protected final byte[] encodingTable = - { - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', - (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' - }; - + { + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', + (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' + }; + /* * set up the decoding table. */ diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Translator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Translator.java index 789823348..819b761ae 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Translator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/encoders/Translator.java @@ -1,7 +1,7 @@ package org.spongycastle.util.encoders; /** - * general interface for an translator. + * General interface for an translator. */ public interface Translator { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java index 8b50bd631..47f85a3fb 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/StreamOverflowException.java @@ -2,6 +2,9 @@ package org.spongycastle.util.io; import java.io.IOException; +/** + * Exception thrown when too much data is written to an InputStream + */ public class StreamOverflowException extends IOException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/Streams.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/Streams.java index fa3a425e2..210620c48 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/Streams.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/Streams.java @@ -5,10 +5,19 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +/** + * Utility methods to assist with stream processing. + */ public final class Streams { private static int BUFFER_SIZE = 512; + /** + * Read stream till EOF is encountered. + * + * @param inStr stream to be emptied. + * @throws IOException in case of underlying IOException. + */ public static void drain(InputStream inStr) throws IOException { @@ -18,6 +27,13 @@ public final class Streams } } + /** + * Read stream fully, returning contents in a byte array. + * + * @param inStr stream to be read. + * @return a byte array representing the contents of inStr. + * @throws IOException in case of underlying IOException. + */ public static byte[] readAll(InputStream inStr) throws IOException { @@ -26,6 +42,15 @@ public final class Streams return buf.toByteArray(); } + /** + * Read from inStr up to a maximum number of bytes, throwing an exception if more the maximum amount + * of requested data is available. + * + * @param inStr stream to be read. + * @param limit maximum number of bytes that can be read. + * @return a byte array representing the contents of inStr. + * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it. + */ public static byte[] readAllLimited(InputStream inStr, int limit) throws IOException { @@ -34,12 +59,30 @@ public final class Streams return buf.toByteArray(); } + /** + * Fully read in buf's length in data, or up to EOF, whichever occurs first, + * + * @param inStr the stream to be read. + * @param buf the buffer to be read into. + * @return the number of bytes read into the buffer. + * @throws IOException in case of underlying IOException. + */ public static int readFully(InputStream inStr, byte[] buf) throws IOException { return readFully(inStr, buf, 0, buf.length); } + /** + * Fully read in len's bytes of data into buf, or up to EOF, whichever occurs first, + * + * @param inStr the stream to be read. + * @param buf the buffer to be read into. + * @param off offset into buf to start putting bytes into. + * @param len the number of bytes to be read. + * @return the number of bytes read into the buffer. + * @throws IOException in case of underlying IOException. + */ public static int readFully(InputStream inStr, byte[] buf, int off, int len) throws IOException { @@ -56,6 +99,13 @@ public final class Streams return totalRead; } + /** + * Write the full contents of inStr to the destination stream outStr. + * + * @param inStr source input stream. + * @param outStr destination output stream. + * @throws IOException in case of underlying IOException. + */ public static void pipeAll(InputStream inStr, OutputStream outStr) throws IOException { @@ -67,6 +117,14 @@ public final class Streams } } + /** + * Write up to limit bytes of data from inStr to the destination stream outStr. + * + * @param inStr source input stream. + * @param limit the maximum number of bytes allowed to be read. + * @param outStr destination output stream. + * @throws IOException in case of underlying IOException, or if limit is reached on inStr still has data in it. + */ public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr) throws IOException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java index 1e62eb548..9647528d4 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeInputStream.java @@ -4,12 +4,21 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +/** + * An input stream which copies anything read through it to another stream. + */ public class TeeInputStream extends InputStream { private final InputStream input; private final OutputStream output; + /** + * Base constructor. + * + * @param input input stream to be wrapped. + * @param output output stream to copy any input read to. + */ public TeeInputStream(InputStream input, OutputStream output) { this.input = input; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java index 9e2317c6d..c7cdcf6ea 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/TeeOutputStream.java @@ -3,12 +3,22 @@ package org.spongycastle.util.io; import java.io.IOException; import java.io.OutputStream; + +/** + * An output stream which copies anything written into it to another stream. + */ public class TeeOutputStream extends OutputStream { private OutputStream output1; private OutputStream output2; + /** + * Base constructor. + * + * @param output1 the output stream that is wrapped. + * @param output2 a secondary stream that anything written to output1 is also written to. + */ public TeeOutputStream(OutputStream output1, OutputStream output2) { this.output1 = output1; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java index 12298fe46..676b82d19 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java @@ -2,6 +2,9 @@ package org.spongycastle.util.io.pem; import java.io.IOException; +/** + * Exception thrown on failure to generate a PEM object. + */ public class PemGenerationException extends IOException { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java index 4adb815e5..142932679 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java @@ -1,10 +1,19 @@ package org.spongycastle.util.io.pem; +/** + * Class representing a PEM header (name, value) pair. + */ public class PemHeader { private String name; private String value; + /** + * Base constructor. + * + * @param name name of the header property. + * @param value value of the header property. + */ public PemHeader(String name, String value) { this.name = name; diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java index bd51777e4..16c5c4f52 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java @@ -4,6 +4,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +/** + * A generic PEM object - type, header properties, and byte content. + */ public class PemObject implements PemObjectGenerator { diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java index 1a8cea6de..0df180cea 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java @@ -1,7 +1,16 @@ package org.spongycastle.util.io.pem; +/** + * Base interface for generators of PEM objects. + */ public interface PemObjectGenerator { + /** + * Generate a PEM object. + * + * @return the generated object. + * @throws PemGenerationException on failure. + */ PemObject generate() throws PemGenerationException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java index 1c6a3eb22..5192078fe 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java @@ -2,8 +2,18 @@ package org.spongycastle.util.io.pem; import java.io.IOException; +/** + * Base interface for parsers to convert PEM objects into specific objects. + */ public interface PemObjectParser { + /** + * Parse an object out of the PEM object passed in. + * + * @param obj the PEM object containing the details for the specific object. + * @return a specific object represented by the PEM object. + * @throws IOException on a parsing error. + */ Object parseObject(PemObject obj) throws IOException; } diff --git a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java index cbbebab97..0b909167d 100644 --- a/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java +++ b/extern/spongycastle/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java @@ -8,6 +8,9 @@ import java.util.List; import org.spongycastle.util.encoders.Base64; +/** + * A generic PEM reader, based on the format outlined in RFC 1421 + */ public class PemReader extends BufferedReader { diff --git a/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java b/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java index 7971e7b61..8d4ed9c44 100644 --- a/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java +++ b/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java @@ -16,7 +16,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.x509.X509Extensions; import org.spongycastle.asn1.x509.X509Name; import org.spongycastle.jce.PrincipalUtil; @@ -562,7 +562,7 @@ public class X509CRLSelector implements CRLSelector ((ASN1OctetString)derInputStream.readObject()) .getOctets()); derInputStream = new ASN1InputStream(inStream); - BigInteger crlNumber = ((DERInteger)derInputStream.readObject()) + BigInteger crlNumber = ((ASN1Integer)derInputStream.readObject()) .getPositiveValue(); if (minCRL != null && minCRL.compareTo(crlNumber) > 0) { diff --git a/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java b/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java index 89767cde5..9292c2e30 100644 --- a/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java +++ b/extern/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java @@ -26,6 +26,7 @@ import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.util.ASN1Dump; @@ -2148,7 +2149,7 @@ public class X509CertSelector implements CertSelector // TODO fix this, Sequence contains tagged objects ASN1Sequence derObject = (ASN1Sequence)derInputStream .readObject(); - DERGeneralizedTime derDate = DERGeneralizedTime + ASN1GeneralizedTime derDate = DERGeneralizedTime .getInstance(derObject.getObjectAt(0)); SimpleDateFormat dateF = new SimpleDateFormat( "yyyyMMddHHmmssZ"); diff --git a/extern/spongycastle/core/src/main/jdk1.1/java/util/Collections.java b/extern/spongycastle/core/src/main/jdk1.1/java/util/Collections.java index 1b7f2e930..efde29b3d 100644 --- a/extern/spongycastle/core/src/main/jdk1.1/java/util/Collections.java +++ b/extern/spongycastle/core/src/main/jdk1.1/java/util/Collections.java @@ -4,7 +4,8 @@ import java.io.Serializable; public class Collections { - public static List EMPTY_LIST = new ArrayList(); + public static final List EMPTY_LIST = unmodifiableList(new ArrayList()); + public static final Set EMPTY_SET = unmodifiableSet(new HashSet()); private Collections() { diff --git a/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java index d8bacbc7c..8c6571def 100644 --- a/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java +++ b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/asn1/ASN1InputStream.java @@ -438,7 +438,7 @@ public class ASN1InputStream case IA5_STRING: return new DERIA5String(defIn.toByteArray()); case INTEGER: - return new ASN1Integer(defIn.toByteArray()); + return new ASN1Integer(defIn.toByteArray(), false); case NULL: return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?) case NUMERIC_STRING: diff --git a/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java index 3149a1f37..7af31f36e 100644 --- a/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java +++ b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/encodings/PKCS1Encoding.java @@ -1,13 +1,13 @@ package org.spongycastle.crypto.encodings; +import java.security.SecureRandom; + import org.spongycastle.crypto.AsymmetricBlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.ParametersWithRandom; -import java.security.SecureRandom; - /** * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this * depends on your application - see PKCS1 Version 2 for details. @@ -32,6 +32,8 @@ public class PKCS1Encoding private boolean forEncryption; private boolean forPrivateKey; private boolean useStrictLength; + private int pLen = -1; + private byte[] fallback = null; /** * Basic constructor. @@ -44,11 +46,48 @@ public class PKCS1Encoding this.useStrictLength = useStrict(); } + /** + * Constructor for decryption with a fixed plaintext length. + * + * @param cipher The cipher to use for cryptographic operation. + * @param pLen Length of the expected plaintext. + */ + public PKCS1Encoding( + AsymmetricBlockCipher cipher, + int pLen) + { + this.engine = cipher; + this.useStrictLength = useStrict(); + this.pLen = pLen; + } + + /** + * Constructor for decryption with a fixed plaintext length and a fallback + * value that is returned, if the padding is incorrect. + * + * @param cipher + * The cipher to use for cryptographic operation. + * @param fallback + * The fallback value, we don't to a arraycopy here. + */ + public PKCS1Encoding( + AsymmetricBlockCipher cipher, + byte[] fallback) + { + this.engine = cipher; + this.useStrictLength = useStrict(); + this.fallback = fallback; + this.pLen = fallback.length; + } + + + // // for J2ME compatibility // private boolean useStrict() { + // required if security manager has been installed. String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY); return strict == null || strict.equals("true"); @@ -174,6 +213,121 @@ public class PKCS1Encoding return engine.processBlock(block, 0, block.length); } + + /** + * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext + * for encryption. + * + * @param encoded The Plaintext. + * @param pLen Expected length of the plaintext. + * @return Either 0, if the encoding is correct, or -1, if it is incorrect. + */ + private static int checkPkcs1Encoding(byte[] encoded, int pLen) { + int correct = 0; + /* + * Check if the first two bytes are 0 2 + */ + correct |= (encoded[0] ^ 2); + + /* + * Now the padding check, check for no 0 byte in the padding + */ + int plen = encoded.length - ( + pLen /* Lenght of the PMS */ + + 1 /* Final 0-byte before PMS */ + ); + + for (int i = 1; i < plen; i++) { + int tmp = encoded[i]; + tmp |= tmp >> 1; + tmp |= tmp >> 2; + tmp |= tmp >> 4; + correct |= (tmp & 1) - 1; + } + + /* + * Make sure the padding ends with a 0 byte. + */ + correct |= encoded[encoded.length - (pLen +1)]; + + /* + * Return 0 or 1, depending on the result. + */ + correct |= correct >> 1; + correct |= correct >> 2; + correct |= correct >> 4; + return ~((correct & 1) - 1); + } + + + /** + * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct. + * + * @param in The encrypted block. + * @param inOff Offset in the encrypted block. + * @param inLen Length of the encrypted block. + * //@param pLen Length of the desired output. + * @return The plaintext without padding, or a random value if the padding was incorrect. + * + * @throws InvalidCipherTextException + */ + private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen) + throws InvalidCipherTextException + { + if (!forPrivateKey) + { + throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); + } + + byte[] block = engine.processBlock(in, inOff, inLen); + byte[] random = null; + if (this.fallback == null) + { + random = new byte[this.pLen]; + this.random.nextBytes(random); + } + else + { + random = fallback; + } + + /* + * TODO: This is a potential dangerous side channel. However, you can + * fix this by changing the RSA engine in a way, that it will always + * return blocks of the same length and prepend them with 0 bytes if + * needed. + */ + if (block.length < getOutputBlockSize()) + { + throw new InvalidCipherTextException("block truncated"); + } + + /* + * TODO: Potential side channel. Fix it by making the engine always + * return blocks of the correct length. + */ + if (useStrictLength && block.length != engine.getOutputBlockSize()) + { + throw new InvalidCipherTextException("block incorrect size"); + } + + /* + * Check the padding. + */ + int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen); + + /* + * Now, to a constant time constant memory copy of the decrypted value + * or the random value, depending on the validity of the padding. + */ + byte[] result = new byte[this.pLen]; + for (int i = 0; i < this.pLen; i++) + { + result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct)); + } + + return result; + } /** * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format. @@ -184,7 +338,15 @@ public class PKCS1Encoding int inLen) throws InvalidCipherTextException { - byte[] block = engine.processBlock(in, inOff, inLen); + /* + * If the length of the expected plaintext is known, we use a constant-time decryption. + * If the decryption fails, we return a random value. + */ + if (this.pLen != -1) { + return this.decodeBlockOrRandom(in, inOff, inLen); + } + + byte[] block = engine.processBlock(in, inOff, inLen); if (block.length < getOutputBlockSize()) { @@ -192,10 +354,20 @@ public class PKCS1Encoding } byte type = block[0]; - - if (type != 1 && type != 2) + + if (forPrivateKey) { - throw new InvalidCipherTextException("unknown block type"); + if (type != 2) + { + throw new InvalidCipherTextException("unknown block type"); + } + } + else + { + if (type != 1) + { + throw new InvalidCipherTextException("unknown block type"); + } } if (useStrictLength && block.length != engine.getOutputBlockSize()) diff --git a/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java new file mode 100644 index 000000000..cd6f7a8c4 --- /dev/null +++ b/extern/spongycastle/core/src/main/jdk1.1/org/spongycastle/crypto/tls/AbstractTlsContext.java @@ -0,0 +1,135 @@ +package org.spongycastle.crypto.tls; + +import java.security.SecureRandom; + +import org.spongycastle.crypto.prng.DigestRandomGenerator; +import org.spongycastle.crypto.prng.RandomGenerator; +import org.spongycastle.util.Times; + +abstract class AbstractTlsContext + implements TlsContext +{ + private static long counter = Times.nanoTime(); + + private synchronized static long nextCounterValue() + { + return ++counter; + } + + private RandomGenerator nonceRandom; + private SecureRandom secureRandom; + private SecurityParameters securityParameters; + + private ProtocolVersion clientVersion = null; + private ProtocolVersion serverVersion = null; + private TlsSession session = null; + private Object userObject = null; + + AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters) + { + secureRandom.setSeed(nextCounterValue()); + secureRandom.setSeed(Times.nanoTime()); + + this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256)); + byte[] nonceSeed = new byte[32]; + secureRandom.nextBytes(nonceSeed); + this.nonceRandom.addSeedMaterial(nonceSeed); + + this.secureRandom = secureRandom; + this.securityParameters = securityParameters; + } + + public RandomGenerator getNonceRandomGenerator() + { + return nonceRandom; + } + + public SecureRandom getSecureRandom() + { + return secureRandom; + } + + public SecurityParameters getSecurityParameters() + { + return securityParameters; + } + + public ProtocolVersion getClientVersion() + { + return clientVersion; + } + + void setClientVersion(ProtocolVersion clientVersion) + { + this.clientVersion = clientVersion; + } + + public ProtocolVersion getServerVersion() + { + return serverVersion; + } + + void setServerVersion(ProtocolVersion serverVersion) + { + this.serverVersion = serverVersion; + } + + public TlsSession getResumableSession() + { + return session; + } + + void setResumableSession(TlsSession session) + { + this.session = session; + } + + public Object getUserObject() + { + return userObject; + } + + public void setUserObject(Object userObject) + { + this.userObject = userObject; + } + + public byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length) + { + if (context_value != null && !TlsUtils.isValidUint16(context_value.length)) + { + throw new IllegalArgumentException("'context_value' must have length less than 2^16 (or be null)"); + } + + SecurityParameters sp = getSecurityParameters(); + byte[] cr = sp.getClientRandom(), sr = sp.getServerRandom(); + + int seedLength = cr.length + sr.length; + if (context_value != null) + { + seedLength += (2 + context_value.length); + } + + byte[] seed = new byte[seedLength]; + int seedPos = 0; + + System.arraycopy(cr, 0, seed, seedPos, cr.length); + seedPos += cr.length; + System.arraycopy(sr, 0, seed, seedPos, sr.length); + seedPos += sr.length; + if (context_value != null) + { + TlsUtils.writeUint16(context_value.length, seed, seedPos); + seedPos += 2; + System.arraycopy(context_value, 0, seed, seedPos, context_value.length); + seedPos += context_value.length; + } + + if (seedPos != seedLength) + { + throw new IllegalStateException("error in calculation of seed for export"); + } + + return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length); + } +} diff --git a/extern/spongycastle/core/src/main/jdk1.3/org/spongycastle/util/Shorts.java b/extern/spongycastle/core/src/main/jdk1.3/org/spongycastle/util/Shorts.java deleted file mode 100644 index 66a992f77..000000000 --- a/extern/spongycastle/core/src/main/jdk1.3/org/spongycastle/util/Shorts.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.spongycastle.util; - -public class Shorts -{ - public static Short valueOf(short value) - { - return new Short(value); - } -} diff --git a/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Integers.java b/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Integers.java index 3ac592d3c..bf6b5e345 100644 --- a/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Integers.java +++ b/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Integers.java @@ -2,6 +2,16 @@ package org.spongycastle.util; public class Integers { + public static int rotateLeft(int i, int distance) + { + return (i << distance) ^ (i >>> -distance); + } + + public static int rotateRight(int i, int distance) + { + return (i >>> distance) ^ (i << -distance); + } + public static Integer valueOf(int value) { return new Integer(value); diff --git a/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Times.java b/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Times.java new file mode 100644 index 000000000..f88b5395c --- /dev/null +++ b/extern/spongycastle/core/src/main/jdk1.4/org/spongycastle/util/Times.java @@ -0,0 +1,11 @@ +package org.spongycastle.util; + +public final class Times +{ + private static long NANOS_PER_MILLI = 1000000L; + + public static long nanoTime() + { + return NANOS_PER_MILLI * System.currentTimeMillis(); + } +} diff --git a/extern/spongycastle/pkix/build.gradle b/extern/spongycastle/pkix/build.gradle index f9bbf77de..639cdae6c 100644 --- a/extern/spongycastle/pkix/build.gradle +++ b/extern/spongycastle/pkix/build.gradle @@ -7,4 +7,4 @@ dependencies { sourceCompatibility = 1.5 targetCompatibility = 1.5 -version = '1.50.0.0' +version = '1.51.0.0' diff --git a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/CertUtils.java b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/CertUtils.java index 73d093a0f..c41d4b5e4 100644 --- a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/CertUtils.java +++ b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/CertUtils.java @@ -14,7 +14,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.DERNull; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.DERSequence; @@ -199,7 +199,7 @@ class CertUtils return null; } - static Date recoverDate(DERGeneralizedTime time) + static Date recoverDate(ASN1GeneralizedTime time) { return time.getDate(); } diff --git a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v1CertificateBuilder.java b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v1CertificateBuilder.java new file mode 100644 index 000000000..282ef9e4c --- /dev/null +++ b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v1CertificateBuilder.java @@ -0,0 +1,83 @@ +package org.spongycastle.cert; + +import java.math.BigInteger; +import java.util.Date; + +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.ExtensionsGenerator; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V1TBSCertificateGenerator; +import org.spongycastle.asn1.x509.V3TBSCertificateGenerator; +import org.spongycastle.operator.ContentSigner; + + +/** + * class to produce an X.509 Version 1 certificate. + */ +public class X509v1CertificateBuilder +{ + private V1TBSCertificateGenerator tbsGen; + + /** + * Create a builder for a version 1 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the date before which the certificate is not valid + * @param notAfter the date after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v1CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + this(issuer, serial, new Time(notBefore), new Time(notAfter), subject, publicKeyInfo); + } + + /** + * Create a builder for a version 1 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the Time before which the certificate is not valid + * @param notAfter the Time after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v1CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + if (issuer == null) + { + throw new IllegalArgumentException("issuer must not be null"); + } + + if (publicKeyInfo == null) + { + throw new IllegalArgumentException("publicKeyInfo must not be null"); + } + + tbsGen = new V1TBSCertificateGenerator(); + tbsGen.setSerialNumber(new ASN1Integer(serial)); + tbsGen.setIssuer(issuer); + tbsGen.setStartDate(notBefore); + tbsGen.setEndDate(notAfter); + tbsGen.setSubject(subject); + tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); + } + + /** + * Generate an X509 certificate, based on the current issuer and subject + * using the passed in signer. + * + * @param signer the content signer to be used to generate the signature validating the certificate. + * @return a holder containing the resulting signed certificate. + */ + public X509CertificateHolder build( + ContentSigner signer) + { + tbsGen.setSignature(signer.getAlgorithmIdentifier()); + + return CertUtils.generateFullCert(signer, tbsGen.generateTBSCertificate()); + } +} diff --git a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java new file mode 100644 index 000000000..fea5400ff --- /dev/null +++ b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java @@ -0,0 +1,138 @@ +package org.spongycastle.cert; + +import java.math.BigInteger; +import java.util.Date; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1GeneralizedTime; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERSet; +import org.spongycastle.asn1.x509.AttCertIssuer; +import org.spongycastle.asn1.x509.Attribute; +import org.spongycastle.asn1.x509.ExtensionsGenerator; +import org.spongycastle.asn1.x509.V2AttributeCertificateInfoGenerator; +import org.spongycastle.operator.ContentSigner; + +/** + * class to produce an X.509 Version 2 AttributeCertificate. + */ +public class X509v2AttributeCertificateBuilder +{ + private V2AttributeCertificateInfoGenerator acInfoGen; + private ExtensionsGenerator extGenerator; + + /** + * Base constructor. + * + * @param holder holder certificate details + * @param issuer issuer of this attribute certificate. + * @param serialNumber serial number of this attribute certificate. + * @param notBefore the date before which the certificate is not valid. + * @param notAfter the date after which the certificate is not valid. + */ + public X509v2AttributeCertificateBuilder(AttributeCertificateHolder holder, AttributeCertificateIssuer issuer, BigInteger serialNumber, Date notBefore, Date notAfter) + { + acInfoGen = new V2AttributeCertificateInfoGenerator(); + extGenerator = new ExtensionsGenerator(); + + acInfoGen.setHolder(holder.holder); + acInfoGen.setIssuer(AttCertIssuer.getInstance(issuer.form)); + acInfoGen.setSerialNumber(new ASN1Integer(serialNumber)); + acInfoGen.setStartDate(new ASN1GeneralizedTime(notBefore)); + acInfoGen.setEndDate(new ASN1GeneralizedTime(notAfter)); + } + + /** + * Add an attribute to the certification request we are building. + * + * @param attrType the OID giving the type of the attribute. + * @param attrValue the ASN.1 structure that forms the value of the attribute. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addAttribute(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue) + { + acInfoGen.addAttribute(new Attribute(attrType, new DERSet(attrValue))); + + return this; + } + + /** + * Add an attribute with multiple values to the certification request we are building. + * + * @param attrType the OID giving the type of the attribute. + * @param attrValues an array of ASN.1 structures that form the value of the attribute. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addAttribute(ASN1ObjectIdentifier attrType, ASN1Encodable[] attrValues) + { + acInfoGen.addAttribute(new Attribute(attrType, new DERSet(attrValues))); + + return this; + } + + public void setIssuerUniqueId( + boolean[] iui) + { + acInfoGen.setIssuerUniqueID(CertUtils.booleanToBitString(iui)); + } + + /** + * Add a given extension field for the standard extensions tag + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param value the ASN.1 structure that forms the extension's value. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + ASN1Encodable value) + throws CertIOException + { + CertUtils.addExtension(extGenerator, oid, isCritical, value); + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + + /** + * Generate an X509 certificate, based on the current issuer and subject + * using the passed in signer. + * + * @param signer the content signer to be used to generate the signature validating the certificate. + * @return a holder containing the resulting signed certificate. + */ + public X509AttributeCertificateHolder build( + ContentSigner signer) + { + acInfoGen.setSignature(signer.getAlgorithmIdentifier()); + + if (!extGenerator.isEmpty()) + { + acInfoGen.setExtensions(extGenerator.generate()); + } + + return CertUtils.generateFullAttrCert(signer, acInfoGen.generateAttributeCertificateInfo()); + } +} diff --git a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2CRLBuilder.java b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2CRLBuilder.java new file mode 100644 index 000000000..d0e9e9608 --- /dev/null +++ b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v2CRLBuilder.java @@ -0,0 +1,231 @@ +package org.spongycastle.cert; + +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1GeneralizedTime; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.Extensions; +import org.spongycastle.asn1.x509.ExtensionsGenerator; +import org.spongycastle.asn1.x509.TBSCertList; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V2TBSCertListGenerator; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.operator.ContentSigner; + +/** + * class to produce an X.509 Version 2 CRL. + */ +public class X509v2CRLBuilder +{ + private V2TBSCertListGenerator tbsGen; + private ExtensionsGenerator extGenerator; + + /** + * Basic constructor. + * + * @param issuer the issuer this CRL is associated with. + * @param thisUpdate the date of this update. + */ + public X509v2CRLBuilder( + X500Name issuer, + Date thisUpdate) + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator = new ExtensionsGenerator(); + + tbsGen.setIssuer(issuer); + tbsGen.setThisUpdate(new Time(thisUpdate)); + } + + /** + * Basic constructor. + * + * @param issuer the issuer this CRL is associated with. + * @param thisUpdate the Time of this update. + */ + public X509v2CRLBuilder( + X500Name issuer, + Time thisUpdate) + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator = new ExtensionsGenerator(); + + tbsGen.setIssuer(issuer); + tbsGen.setThisUpdate(thisUpdate); + } + + /** + * Set the date by which the next CRL will become available. + * + * @param date date of next CRL update. + * @return the current builder. + */ + public X509v2CRLBuilder setNextUpdate( + Date date) + { + return this.setNextUpdate(new Time(date)); + } + + /** + * Set the date by which the next CRL will become available. + * + * @param date date of next CRL update. + * @return the current builder. + */ + public X509v2CRLBuilder setNextUpdate( + Time date) + { + tbsGen.setNextUpdate(date); + + return this; + } + + /** + * Add a CRL entry with the just reasonCode extension. + * + * @param userCertificateSerial serial number of revoked certificate. + * @param revocationDate date of certificate revocation. + * @param reason the reason code, as indicated in CRLReason, i.e CRLReason.keyCompromise, or 0 if not to be used. + * @return the current builder. + */ + public X509v2CRLBuilder addCRLEntry(BigInteger userCertificateSerial, Date revocationDate, int reason) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificateSerial), new Time(revocationDate), reason); + + return this; + } + + /** + * Add a CRL entry with an invalidityDate extension as well as a reasonCode extension. This is used + * where the date of revocation might be after issues with the certificate may have occurred. + * + * @param userCertificateSerial serial number of revoked certificate. + * @param revocationDate date of certificate revocation. + * @param reason the reason code, as indicated in CRLReason, i.e CRLReason.keyCompromise, or 0 if not to be used. + * @param invalidityDate the date on which the private key for the certificate became compromised or the certificate otherwise became invalid. + * @return the current builder. + */ + public X509v2CRLBuilder addCRLEntry(BigInteger userCertificateSerial, Date revocationDate, int reason, Date invalidityDate) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificateSerial), new Time(revocationDate), reason, new ASN1GeneralizedTime(invalidityDate)); + + return this; + } + + /** + * Add a CRL entry with extensions. + * + * @param userCertificateSerial serial number of revoked certificate. + * @param revocationDate date of certificate revocation. + * @param extensions extension set to be associated with this CRLEntry. + * @return the current builder. + * @deprecated use method taking Extensions + */ + public X509v2CRLBuilder addCRLEntry(BigInteger userCertificateSerial, Date revocationDate, X509Extensions extensions) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificateSerial), new Time(revocationDate), Extensions.getInstance(extensions)); + + return this; + } + + /** + * Add a CRL entry with extensions. + * + * @param userCertificateSerial serial number of revoked certificate. + * @param revocationDate date of certificate revocation. + * @param extensions extension set to be associated with this CRLEntry. + * @return the current builder. + */ + public X509v2CRLBuilder addCRLEntry(BigInteger userCertificateSerial, Date revocationDate, Extensions extensions) + { + tbsGen.addCRLEntry(new ASN1Integer(userCertificateSerial), new Time(revocationDate), extensions); + + return this; + } + + /** + * Add the CRLEntry objects contained in a previous CRL. + * + * @param other the X509CRLHolder to source the other entries from. + * @return the current builder. + */ + public X509v2CRLBuilder addCRL(X509CRLHolder other) + { + TBSCertList revocations = other.toASN1Structure().getTBSCertList(); + + if (revocations != null) + { + for (Enumeration en = revocations.getRevokedCertificateEnumeration(); en.hasMoreElements();) + { + tbsGen.addCRLEntry(ASN1Sequence.getInstance(((ASN1Encodable)en.nextElement()).toASN1Primitive())); + } + } + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param value the ASN.1 structure that forms the extension's value. + * @return this builder object. + */ + public X509v2CRLBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + ASN1Encodable value) + throws CertIOException + { + CertUtils.addExtension(extGenerator, oid, isCritical, value); + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v2CRLBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + + /** + * Generate an X.509 CRL, based on the current issuer and subject + * using the passed in signer. + * + * @param signer the content signer to be used to generate the signature validating the certificate. + * @return a holder containing the resulting signed certificate. + */ + public X509CRLHolder build( + ContentSigner signer) + { + tbsGen.setSignature(signer.getAlgorithmIdentifier()); + + if (!extGenerator.isEmpty()) + { + tbsGen.setExtensions(extGenerator.generate()); + } + + return CertUtils.generateFullCRL(signer, tbsGen.generateTBSCertList()); + } +} diff --git a/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v3CertificateBuilder.java b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v3CertificateBuilder.java new file mode 100644 index 000000000..f4f40ba0a --- /dev/null +++ b/extern/spongycastle/pkix/src/main/j2me/org/spongycastle/cert/X509v3CertificateBuilder.java @@ -0,0 +1,177 @@ +package org.spongycastle.cert; + +import java.math.BigInteger; +import java.util.Date; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.Certificate; +import org.spongycastle.asn1.x509.Extension; +import org.spongycastle.asn1.x509.ExtensionsGenerator; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.Time; +import org.spongycastle.asn1.x509.V3TBSCertificateGenerator; +import org.spongycastle.operator.ContentSigner; + + +/** + * class to produce an X.509 Version 3 certificate. + */ +public class X509v3CertificateBuilder +{ + private V3TBSCertificateGenerator tbsGen; + private ExtensionsGenerator extGenerator; + + /** + * Create a builder for a version 3 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the date before which the certificate is not valid + * @param notAfter the date after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + this(issuer, serial, new Time(notBefore), new Time(notAfter), subject, publicKeyInfo); + } + + /** + * Create a builder for a version 3 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the Time before which the certificate is not valid + * @param notAfter the Time after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + tbsGen = new V3TBSCertificateGenerator(); + tbsGen.setSerialNumber(new ASN1Integer(serial)); + tbsGen.setIssuer(issuer); + tbsGen.setStartDate(notBefore); + tbsGen.setEndDate(notAfter); + tbsGen.setSubject(subject); + tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); + + extGenerator = new ExtensionsGenerator(); + } + + /** + * Set the subjectUniqueID - note: it is very rare that it is correct to do this. + * + * @param uniqueID a boolean array representing the bits making up the subjectUniqueID. + * @return this builder object. + */ + public X509v3CertificateBuilder setSubjectUniqueID(boolean[] uniqueID) + { + tbsGen.setSubjectUniqueID(CertUtils.booleanToBitString(uniqueID)); + + return this; + } + + /** + * Set the issuerUniqueID - note: it is very rare that it is correct to do this. + * + * @param uniqueID a boolean array representing the bits making up the issuerUniqueID. + * @return this builder object. + */ + public X509v3CertificateBuilder setIssuerUniqueID(boolean[] uniqueID) + { + tbsGen.setIssuerUniqueID(CertUtils.booleanToBitString(uniqueID)); + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param value the ASN.1 structure that forms the extension's value. + * @return this builder object. + */ + public X509v3CertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + ASN1Encodable value) + throws CertIOException + { + CertUtils.addExtension(extGenerator, oid, isCritical, value); + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v3CertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + + /** + * Add a given extension field for the standard extensions tag (tag 3) + * copying the extension value from another certificate. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the copied extension is to be marked as critical, false otherwise. + * @param certHolder the holder for the certificate that the extension is to be copied from. + * @return this builder object. + */ + public X509v3CertificateBuilder copyAndAddExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + X509CertificateHolder certHolder) + { + Certificate cert = certHolder.toASN1Structure(); + + Extension extension = cert.getTBSCertificate().getExtensions().getExtension(oid); + + if (extension == null) + { + throw new NullPointerException("extension " + oid + " not present"); + } + + extGenerator.addExtension(oid, isCritical, extension.getExtnValue().getOctets()); + + return this; + } + + /** + * Generate an X.509 certificate, based on the current issuer and subject + * using the passed in signer. + * + * @param signer the content signer to be used to generate the signature validating the certificate. + * @return a holder containing the resulting signed certificate. + */ + public X509CertificateHolder build( + ContentSigner signer) + { + tbsGen.setSignature(signer.getAlgorithmIdentifier()); + + if (!extGenerator.isEmpty()) + { + tbsGen.setExtensions(extGenerator.generate()); + } + + return CertUtils.generateFullCert(signer, tbsGen.generateTBSCertificate()); + } +} diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509ExtensionUtils.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509ExtensionUtils.java index 54f56adb8..96e603f82 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509ExtensionUtils.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509ExtensionUtils.java @@ -2,6 +2,7 @@ package org.spongycastle.cert; import java.io.IOException; import java.io.OutputStream; +import java.math.BigInteger; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; @@ -65,6 +66,11 @@ public class X509ExtensionUtils return new AuthorityKeyIdentifier(calculateIdentifier(publicKeyInfo)); } + public AuthorityKeyIdentifier createAuthorityKeyIdentifier(SubjectPublicKeyInfo publicKeyInfo, GeneralNames generalNames, BigInteger serial) + { + return new AuthorityKeyIdentifier(calculateIdentifier(publicKeyInfo), generalNames, serial); + } + /** * Return a RFC 3280 type 1 key identifier. As in: *
diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v1CertificateBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v1CertificateBuilder.java index b0a9b497f..083e15059 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v1CertificateBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v1CertificateBuilder.java @@ -2,12 +2,15 @@ package org.spongycastle.cert; import java.math.BigInteger; import java.util.Date; +import java.util.Locale; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.ExtensionsGenerator; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x509.Time; import org.spongycastle.asn1.x509.V1TBSCertificateGenerator; +import org.spongycastle.asn1.x509.V3TBSCertificateGenerator; import org.spongycastle.operator.ContentSigner; @@ -30,25 +33,57 @@ public class X509v1CertificateBuilder */ public X509v1CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) { - if (issuer == null) - { - throw new IllegalArgumentException("issuer must not be null"); - } - - if (publicKeyInfo == null) - { - throw new IllegalArgumentException("publicKeyInfo must not be null"); - } - - tbsGen = new V1TBSCertificateGenerator(); - tbsGen.setSerialNumber(new ASN1Integer(serial)); - tbsGen.setIssuer(issuer); - tbsGen.setStartDate(new Time(notBefore)); - tbsGen.setEndDate(new Time(notAfter)); - tbsGen.setSubject(subject); - tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); + this(issuer, serial, new Time(notBefore), new Time(notAfter), subject, publicKeyInfo); } + /** + * Create a builder for a version 1 certificate. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the Time produced is compatible with other ASN.1 implementations. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the date before which the certificate is not valid + * @param notAfter the date after which the certificate is not valid + * @param dateLocale locale to be used for date interpretation. + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v1CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, Locale dateLocale, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + this(issuer, serial, new Time(notBefore, dateLocale), new Time(notAfter, dateLocale), subject, publicKeyInfo); + } + + /** + * Create a builder for a version 1 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the Time before which the certificate is not valid + * @param notAfter the Time after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v1CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + if (issuer == null) + { + throw new IllegalArgumentException("issuer must not be null"); + } + + if (publicKeyInfo == null) + { + throw new IllegalArgumentException("publicKeyInfo must not be null"); + } + + tbsGen = new V1TBSCertificateGenerator(); + tbsGen.setSerialNumber(new ASN1Integer(serial)); + tbsGen.setIssuer(issuer); + tbsGen.setStartDate(notBefore); + tbsGen.setEndDate(notAfter); + tbsGen.setSubject(subject); + tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); + } + /** * Generate an X509 certificate, based on the current issuer and subject * using the passed in signer. diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java index 199bb9b4d..ffdd1567b 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2AttributeCertificateBuilder.java @@ -2,6 +2,7 @@ package org.spongycastle.cert; import java.math.BigInteger; import java.util.Date; +import java.util.Locale; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1GeneralizedTime; @@ -22,7 +23,16 @@ public class X509v2AttributeCertificateBuilder private V2AttributeCertificateInfoGenerator acInfoGen; private ExtensionsGenerator extGenerator; - public X509v2AttributeCertificateBuilder(AttributeCertificateHolder holder, AttributeCertificateIssuer issuer, BigInteger serialNumber, Date notBefore, Date notAfter) + /** + * Base constructor. + * + * @param holder holder certificate details + * @param issuer issuer of this attribute certificate. + * @param serialNumber serial number of this attribute certificate. + * @param notBefore the date before which the certificate is not valid. + * @param notAfter the date after which the certificate is not valid. + */ + public X509v2AttributeCertificateBuilder(AttributeCertificateHolder holder, AttributeCertificateIssuer issuer, BigInteger serialNumber, Date notBefore, Date notAfter) { acInfoGen = new V2AttributeCertificateInfoGenerator(); extGenerator = new ExtensionsGenerator(); @@ -34,6 +44,29 @@ public class X509v2AttributeCertificateBuilder acInfoGen.setEndDate(new ASN1GeneralizedTime(notAfter)); } + /** + * Base constructor with locale for interpreting dates. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. + * + * @param holder holder certificate details + * @param issuer issuer of this attribute certificate. + * @param serialNumber serial number of this attribute certificate. + * @param notBefore the date before which the certificate is not valid. + * @param notAfter the date after which the certificate is not valid. + * @param dateLocale locale to be used for date interpretation. + */ + public X509v2AttributeCertificateBuilder(AttributeCertificateHolder holder, AttributeCertificateIssuer issuer, BigInteger serialNumber, Date notBefore, Date notAfter, Locale dateLocale) + { + acInfoGen = new V2AttributeCertificateInfoGenerator(); + extGenerator = new ExtensionsGenerator(); + + acInfoGen.setHolder(holder.holder); + acInfoGen.setIssuer(AttCertIssuer.getInstance(issuer.form)); + acInfoGen.setSerialNumber(new ASN1Integer(serialNumber)); + acInfoGen.setStartDate(new ASN1GeneralizedTime(notBefore, dateLocale)); + acInfoGen.setEndDate(new ASN1GeneralizedTime(notAfter, dateLocale)); + } + /** * Add an attribute to the certification request we are building. * @@ -87,6 +120,26 @@ public class X509v2AttributeCertificateBuilder return this; } + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v2AttributeCertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + /** * Generate an X509 certificate, based on the current issuer and subject * using the passed in signer. diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2CRLBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2CRLBuilder.java index d4b211cab..69cb24063 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2CRLBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v2CRLBuilder.java @@ -3,6 +3,7 @@ package org.spongycastle.cert; import java.math.BigInteger; import java.util.Date; import java.util.Enumeration; +import java.util.Locale; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1GeneralizedTime; @@ -43,6 +44,43 @@ public class X509v2CRLBuilder tbsGen.setThisUpdate(new Time(thisUpdate)); } + /** + * Basic constructor with Locale. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the Time produced is compatible with other ASN.1 implementations. + * + * @param issuer the issuer this CRL is associated with. + * @param thisUpdate the date of this update. + * @param dateLocale locale to be used for date interpretation. + */ + public X509v2CRLBuilder( + X500Name issuer, + Date thisUpdate, + Locale dateLocale) + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator = new ExtensionsGenerator(); + + tbsGen.setIssuer(issuer); + tbsGen.setThisUpdate(new Time(thisUpdate, dateLocale)); + } + + /** + * Basic constructor. + * + * @param issuer the issuer this CRL is associated with. + * @param thisUpdate the Time of this update. + */ + public X509v2CRLBuilder( + X500Name issuer, + Time thisUpdate) + { + tbsGen = new V2TBSCertListGenerator(); + extGenerator = new ExtensionsGenerator(); + + tbsGen.setIssuer(issuer); + tbsGen.setThisUpdate(thisUpdate); + } + /** * Set the date by which the next CRL will become available. * @@ -52,7 +90,33 @@ public class X509v2CRLBuilder public X509v2CRLBuilder setNextUpdate( Date date) { - tbsGen.setNextUpdate(new Time(date)); + return this.setNextUpdate(new Time(date)); + } + + /** + * Set the date by which the next CRL will become available. + * + * @param date date of next CRL update. + * @param dateLocale locale to be used for date interpretation. + * @return the current builder. + */ + public X509v2CRLBuilder setNextUpdate( + Date date, + Locale dateLocale) + { + return this.setNextUpdate(new Time(date, dateLocale)); + } + + /** + * Set the date by which the next CRL will become available. + * + * @param date date of next CRL update. + * @return the current builder. + */ + public X509v2CRLBuilder setNextUpdate( + Time date) + { + tbsGen.setNextUpdate(date); return this; } @@ -160,6 +224,26 @@ public class X509v2CRLBuilder return this; } + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v2CRLBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + /** * Generate an X.509 CRL, based on the current issuer and subject * using the passed in signer. diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v3CertificateBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v3CertificateBuilder.java index c2082293d..0b55b2aa4 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v3CertificateBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/X509v3CertificateBuilder.java @@ -2,6 +2,7 @@ package org.spongycastle.cert; import java.math.BigInteger; import java.util.Date; +import java.util.Locale; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Integer; @@ -35,12 +36,44 @@ public class X509v3CertificateBuilder * @param publicKeyInfo the info structure for the public key to be associated with this certificate. */ public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + this(issuer, serial, new Time(notBefore), new Time(notAfter), subject, publicKeyInfo); + } + + /** + * Create a builder for a version 3 certificate. You may need to use this constructor if the default locale + * doesn't use a Gregorian calender so that the Time produced is compatible with other ASN.1 implementations. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the date before which the certificate is not valid + * @param notAfter the date after which the certificate is not valid + * @param dateLocale locale to be used for date interpretation. + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, Locale dateLocale, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) + { + this(issuer, serial, new Time(notBefore, dateLocale), new Time(notAfter, dateLocale), subject, publicKeyInfo); + } + + /** + * Create a builder for a version 3 certificate. + * + * @param issuer the certificate issuer + * @param serial the certificate serial number + * @param notBefore the Time before which the certificate is not valid + * @param notAfter the Time after which the certificate is not valid + * @param subject the certificate subject + * @param publicKeyInfo the info structure for the public key to be associated with this certificate. + */ + public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) { tbsGen = new V3TBSCertificateGenerator(); tbsGen.setSerialNumber(new ASN1Integer(serial)); tbsGen.setIssuer(issuer); - tbsGen.setStartDate(new Time(notBefore)); - tbsGen.setEndDate(new Time(notAfter)); + tbsGen.setStartDate(notBefore); + tbsGen.setEndDate(notAfter); tbsGen.setSubject(subject); tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); @@ -92,6 +125,26 @@ public class X509v3CertificateBuilder return this; } + /** + * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the + * extension value. + * + * @param oid the OID defining the extension type. + * @param isCritical true if the extension is critical, false otherwise. + * @param encodedValue a byte array representing the encoding of the extension value. + * @return this builder object. + */ + public X509v3CertificateBuilder addExtension( + ASN1ObjectIdentifier oid, + boolean isCritical, + byte[] encodedValue) + throws CertIOException + { + extGenerator.addExtension(oid, isCritical, encodedValue); + + return this; + } + /** * Add a given extension field for the standard extensions tag (tag 3) * copying the extension value from another certificate. diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java similarity index 92% rename from extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java rename to extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java index 5dd1ce30f..756acd7da 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java @@ -1,7 +1,8 @@ -package org.spongycastle.cert.crmf; +package org.spongycastle.cert.crmf.bc; import java.security.SecureRandom; +import org.spongycastle.cert.crmf.EncryptedValuePadder; import org.spongycastle.crypto.Digest; import org.spongycastle.crypto.digests.SHA1Digest; import org.spongycastle.crypto.generators.MGF1BytesGenerator; @@ -10,7 +11,7 @@ import org.spongycastle.crypto.params.MGFParameters; /** * An encrypted value padder that uses MGF1 as the basis of the padding. */ -public class FixedLengthMGF1Padder +public class BcFixedLengthMGF1Padder implements EncryptedValuePadder { private int length; @@ -23,7 +24,7 @@ public class FixedLengthMGF1Padder * * @param length fixed length for padded output. */ - public FixedLengthMGF1Padder(int length) + public BcFixedLengthMGF1Padder(int length) { this(length, null); } @@ -36,7 +37,7 @@ public class FixedLengthMGF1Padder * @param length fixed length for padded output. * @param random a source of randomness. */ - public FixedLengthMGF1Padder(int length, SecureRandom random) + public BcFixedLengthMGF1Padder(int length, SecureRandom random) { this.length = length; this.random = random; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java index 212ac914d..92d7faa6b 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java @@ -41,8 +41,8 @@ import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cms.CMSAlgorithm; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.JcaJceUtils; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceUtils; class CRMFHelper { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java index 1aabc3b95..9b10e78e6 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java @@ -12,9 +12,9 @@ import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.CertificateRequestMessage; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; public class JcaCertificateRequestMessage extends CertificateRequestMessage diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java index 870c4b3b8..8ad510bbe 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java @@ -17,9 +17,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.ValueDecryptorGenerator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.InputDecryptor; public class JceAsymmetricValueDecryptorGenerator diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java index 8226bb3b6..6147184f3 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java @@ -14,9 +14,9 @@ import javax.crypto.SecretKey; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OutputEncryptor; import org.spongycastle.operator.jcajce.JceGenericKey; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java index c11f9535e..ceaf78cb8 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java @@ -10,9 +10,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.PKMACValuesCalculator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; public class JcePKMACValuesCalculator implements PKMACValuesCalculator diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaAttributeCertificateIssuer.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaAttributeCertificateIssuer.java new file mode 100644 index 000000000..54ee46ee3 --- /dev/null +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaAttributeCertificateIssuer.java @@ -0,0 +1,32 @@ +package org.spongycastle.cert.jcajce; + +import java.security.cert.X509Certificate; + +import javax.security.auth.x500.X500Principal; + +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.cert.AttributeCertificateIssuer; + +public class JcaAttributeCertificateIssuer + extends AttributeCertificateIssuer +{ + /** + * Base constructor. + * + * @param issuerCert certificate for the issuer of the attribute certificate. + */ + public JcaAttributeCertificateIssuer(X509Certificate issuerCert) + { + this(issuerCert.getIssuerX500Principal()); + } + + /** + * Base constructor. + * + * @param issuerDN X.500 DN for the issuer of the attribute certificate. + */ + public JcaAttributeCertificateIssuer(X500Principal issuerDN) + { + super(X500Name.getInstance(issuerDN.getEncoded())); + } +} diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java index 12f01fbef..b601e24e7 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java @@ -3,17 +3,23 @@ package org.spongycastle.cert.jcajce; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import javax.security.auth.x500.X500Principal; + import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.GeneralNames; import org.spongycastle.asn1.x509.SubjectKeyIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.cert.X509ExtensionUtils; @@ -52,6 +58,16 @@ public class JcaX509ExtensionUtils return super.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded())); } + public AuthorityKeyIdentifier createAuthorityKeyIdentifier(PublicKey pubKey, X500Principal name, BigInteger serial) + { + return super.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()), new GeneralNames(new GeneralName(X500Name.getInstance(name.getEncoded()))), serial); + } + + public AuthorityKeyIdentifier createAuthorityKeyIdentifier(PublicKey pubKey, GeneralNames generalNames, BigInteger serial) + { + return super.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()), generalNames, serial); + } + /** * Return a RFC 3280 type 1 key identifier. As in: *diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509v3CertificateBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509v3CertificateBuilder.java index c61654c1d..238edbe82 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509v3CertificateBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/jcajce/JcaX509v3CertificateBuilder.java @@ -11,6 +11,7 @@ import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.Time; import org.spongycastle.cert.X509v3CertificateBuilder; /** @@ -34,6 +35,21 @@ public class JcaX509v3CertificateBuilder super(issuer, serial, notBefore, notAfter, subject, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); } + /** + * Initialise the builder using a PublicKey. + * + * @param issuer X500Name representing the issuer of this certificate. + * @param serial the serial number for the certificate. + * @param notBefore Time before which the certificate is not valid. + * @param notAfter Time after which the certificate is not valid. + * @param subject X500Name representing the subject of this certificate. + * @param publicKey the public key to be associated with the certificate. + */ + public JcaX509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, PublicKey publicKey) + { + super(issuer, serial, notBefore, notAfter, subject, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); + } + /** * Initialise the builder using X500Principal objects and a PublicKey. * diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/ocsp/BasicOCSPRespBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/ocsp/BasicOCSPRespBuilder.java index 32b50d1cf..ac759de6d 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/ocsp/BasicOCSPRespBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/ocsp/BasicOCSPRespBuilder.java @@ -39,8 +39,8 @@ public class BasicOCSPRespBuilder { CertificateID certId; CertStatus certStatus; - DERGeneralizedTime thisUpdate; - DERGeneralizedTime nextUpdate; + ASN1GeneralizedTime thisUpdate; + ASN1GeneralizedTime nextUpdate; Extensions extensions; public ResponseObject( diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/selector/MSOutlookKeyIdCalculator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/selector/MSOutlookKeyIdCalculator.java index e52e6222e..23748ac32 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/selector/MSOutlookKeyIdCalculator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cert/selector/MSOutlookKeyIdCalculator.java @@ -4,14 +4,16 @@ import java.io.IOException; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.crypto.Digest; -import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.util.Pack; class MSOutlookKeyIdCalculator { + // This is less than ideal, but it seems to be the best way of supporting this without exposing SHA-1 + // as the class is only used to workout the MSOutlook Key ID, you can think of the fact it's SHA-1 as + // a coincidence... static byte[] calculateKeyId(SubjectPublicKeyInfo info) { - Digest dig = new SHA1Digest(); // TODO: include definition of SHA-1 here + SHA1Digest dig = new SHA1Digest(); byte[] hash = new byte[dig.getDigestSize()]; byte[] spkiEnc = new byte[0]; try @@ -30,4 +32,391 @@ class MSOutlookKeyIdCalculator return hash; } + + private static abstract class GeneralDigest + { + private static final int BYTE_LENGTH = 64; + private byte[] xBuf; + private int xBufOff; + + private long byteCount; + + /** + * Standard constructor + */ + protected GeneralDigest() + { + xBuf = new byte[4]; + xBufOff = 0; + } + + /** + * Copy constructor. We are using copy constructors in place + * of the Object.clone() interface as this interface is not + * supported by J2ME. + */ + protected GeneralDigest(GeneralDigest t) + { + xBuf = new byte[t.xBuf.length]; + + copyIn(t); + } + + protected void copyIn(GeneralDigest t) + { + System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); + + xBufOff = t.xBufOff; + byteCount = t.byteCount; + } + + public void update( + byte in) + { + xBuf[xBufOff++] = in; + + if (xBufOff == xBuf.length) + { + processWord(xBuf, 0); + xBufOff = 0; + } + + byteCount++; + } + + public void update( + byte[] in, + int inOff, + int len) + { + // + // fill the current word + // + while ((xBufOff != 0) && (len > 0)) + { + update(in[inOff]); + + inOff++; + len--; + } + + // + // process whole words. + // + while (len > xBuf.length) + { + processWord(in, inOff); + + inOff += xBuf.length; + len -= xBuf.length; + byteCount += xBuf.length; + } + + // + // load in the remainder. + // + while (len > 0) + { + update(in[inOff]); + + inOff++; + len--; + } + } + + public void finish() + { + long bitLength = (byteCount << 3); + + // + // add the pad bytes. + // + update((byte)128); + + while (xBufOff != 0) + { + update((byte)0); + } + + processLength(bitLength); + + processBlock(); + } + + public void reset() + { + byteCount = 0; + + xBufOff = 0; + for (int i = 0; i < xBuf.length; i++) + { + xBuf[i] = 0; + } + } + + protected abstract void processWord(byte[] in, int inOff); + + protected abstract void processLength(long bitLength); + + protected abstract void processBlock(); + } + + private static class SHA1Digest + extends GeneralDigest + { + private static final int DIGEST_LENGTH = 20; + + private int H1, H2, H3, H4, H5; + + private int[] X = new int[80]; + private int xOff; + + /** + * Standard constructor + */ + public SHA1Digest() + { + reset(); + } + + public String getAlgorithmName() + { + return "SHA-1"; + } + + public int getDigestSize() + { + return DIGEST_LENGTH; + } + + protected void processWord( + byte[] in, + int inOff) + { + // Note: Inlined for performance + // X[xOff] = Pack.bigEndianToInt(in, inOff); + int n = in[ inOff] << 24; + n |= (in[++inOff] & 0xff) << 16; + n |= (in[++inOff] & 0xff) << 8; + n |= (in[++inOff] & 0xff); + X[xOff] = n; + + if (++xOff == 16) + { + processBlock(); + } + } + + protected void processLength( + long bitLength) + { + if (xOff > 14) + { + processBlock(); + } + + X[14] = (int)(bitLength >>> 32); + X[15] = (int)(bitLength & 0xffffffff); + } + + public int doFinal( + byte[] out, + int outOff) + { + finish(); + + Pack.intToBigEndian(H1, out, outOff); + Pack.intToBigEndian(H2, out, outOff + 4); + Pack.intToBigEndian(H3, out, outOff + 8); + Pack.intToBigEndian(H4, out, outOff + 12); + Pack.intToBigEndian(H5, out, outOff + 16); + + reset(); + + return DIGEST_LENGTH; + } + + /** + * reset the chaining variables + */ + public void reset() + { + super.reset(); + + H1 = 0x67452301; + H2 = 0xefcdab89; + H3 = 0x98badcfe; + H4 = 0x10325476; + H5 = 0xc3d2e1f0; + + xOff = 0; + for (int i = 0; i != X.length; i++) + { + X[i] = 0; + } + } + + // + // Additive constants + // + private static final int Y1 = 0x5a827999; + private static final int Y2 = 0x6ed9eba1; + private static final int Y3 = 0x8f1bbcdc; + private static final int Y4 = 0xca62c1d6; + + private int f( + int u, + int v, + int w) + { + return ((u & v) | ((~u) & w)); + } + + private int h( + int u, + int v, + int w) + { + return (u ^ v ^ w); + } + + private int g( + int u, + int v, + int w) + { + return ((u & v) | (u & w) | (v & w)); + } + + protected void processBlock() + { + // + // expand 16 word block into 80 word block. + // + for (int i = 16; i < 80; i++) + { + int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]; + X[i] = t << 1 | t >>> 31; + } + + // + // set up working variables. + // + int A = H1; + int B = H2; + int C = H3; + int D = H4; + int E = H5; + + // + // round 1 + // + int idx = 0; + + for (int j = 0; j < 4; j++) + { + // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1 + // B = rotateLeft(B, 30) + E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1; + B = B << 30 | B >>> 2; + + D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1; + A = A << 30 | A >>> 2; + + C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1; + E = E << 30 | E >>> 2; + + B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1; + D = D << 30 | D >>> 2; + + A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1; + C = C << 30 | C >>> 2; + } + + // + // round 2 + // + for (int j = 0; j < 4; j++) + { + // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2 + // B = rotateLeft(B, 30) + E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2; + B = B << 30 | B >>> 2; + + D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2; + A = A << 30 | A >>> 2; + + C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2; + E = E << 30 | E >>> 2; + + B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2; + D = D << 30 | D >>> 2; + + A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2; + C = C << 30 | C >>> 2; + } + + // + // round 3 + // + for (int j = 0; j < 4; j++) + { + // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3 + // B = rotateLeft(B, 30) + E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3; + B = B << 30 | B >>> 2; + + D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3; + A = A << 30 | A >>> 2; + + C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3; + E = E << 30 | E >>> 2; + + B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3; + D = D << 30 | D >>> 2; + + A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3; + C = C << 30 | C >>> 2; + } + + // + // round 4 + // + for (int j = 0; j <= 3; j++) + { + // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4 + // B = rotateLeft(B, 30) + E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4; + B = B << 30 | B >>> 2; + + D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4; + A = A << 30 | A >>> 2; + + C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4; + E = E << 30 | E >>> 2; + + B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4; + D = D << 30 | D >>> 2; + + A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4; + C = C << 30 | C >>> 2; + } + + + H1 += A; + H2 += B; + H3 += C; + H4 += D; + H5 += E; + + // + // reset start of the buffer. + // + xOff = 0; + for (int i = 0; i < 16; i++) + { + X[i] = 0; + } + } + } } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataParser.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataParser.java index b524b4ac9..61a95e53f 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataParser.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataParser.java @@ -109,7 +109,7 @@ public class CMSAuthenticatedDataParser this.authData = new AuthenticatedDataParser((ASN1SequenceParser)_contentInfo.getContent(BERTags.SEQUENCE)); // TODO Validate version? - //DERInteger version = this.authData.getVersion(); + //ASN1Integer version = this.authData.getVersion(); OriginatorInfo info = authData.getOriginatorInfo(); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataStreamGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataStreamGenerator.java index 739b0b1d5..14fbaa207 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataStreamGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedDataStreamGenerator.java @@ -9,11 +9,11 @@ import java.util.Map; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.BERSequenceGenerator; import org.spongycastle.asn1.BERSet; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSet; import org.spongycastle.asn1.DERTaggedObject; @@ -161,7 +161,7 @@ public class CMSAuthenticatedDataStreamGenerator // BERSequenceGenerator authGen = new BERSequenceGenerator(cGen.getRawOutputStream(), 0, true); - authGen.addObject(new DERInteger(AuthenticatedData.calculateVersion(originatorInfo))); + authGen.addObject(new ASN1Integer(AuthenticatedData.calculateVersion(originatorInfo))); if (originatorInfo != null) { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedGenerator.java index d5ea1b8cf..718b09c00 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSAuthenticatedGenerator.java @@ -5,6 +5,7 @@ import java.util.Map; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.util.Arrays; public class CMSAuthenticatedGenerator extends CMSEnvelopedGenerator @@ -34,7 +35,7 @@ public class CMSAuthenticatedGenerator Map param = new HashMap(); param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType); param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId); - param.put(CMSAttributeTableGenerator.DIGEST, hash.clone()); + param.put(CMSAttributeTableGenerator.DIGEST, Arrays.clone(hash)); return param; } } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSEnvelopedDataParser.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSEnvelopedDataParser.java index 45d602e2a..ae821a6a7 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSEnvelopedDataParser.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSEnvelopedDataParser.java @@ -78,7 +78,7 @@ public class CMSEnvelopedDataParser this.envelopedData = new EnvelopedDataParser((ASN1SequenceParser)_contentInfo.getContent(BERTags.SEQUENCE)); // TODO Validate version? - //DERInteger version = this._envelopedData.getVersion(); + //ASN1Integer version = this._envelopedData.getVersion(); OriginatorInfo info = this.envelopedData.getOriginatorInfo(); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedData.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedData.java index cea2c955a..f8127d6d5 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedData.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedData.java @@ -471,7 +471,7 @@ public class CMSSignedData * @param signedData the signed data object to be used as a base. * @param certificates the new certificates to be used. * @param attrCerts the new attribute certificates to be used. - * @param crls the new CRLs to be used. + * @param revocations the new CRLs to be used - a collection of X509CRLHolder objects, OtherRevocationInfoFormat, or both. * @return a new signed data object. * @exception CMSException if there is an error processing the CertStore */ @@ -479,7 +479,7 @@ public class CMSSignedData CMSSignedData signedData, Store certificates, Store attrCerts, - Store crls) + Store revocations) throws CMSException { // @@ -488,7 +488,7 @@ public class CMSSignedData CMSSignedData cms = new CMSSignedData(signedData); // - // replace the certs and crls in the SignedData object + // replace the certs and revocations in the SignedData object // ASN1Set certSet = null; ASN1Set crlSet = null; @@ -514,9 +514,9 @@ public class CMSSignedData } } - if (crls != null) + if (revocations != null) { - ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(crls)); + ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(revocations)); if (set.size() != 0) { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedDataGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedDataGenerator.java index 529ca14a9..70dce12a9 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedDataGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSSignedDataGenerator.java @@ -140,7 +140,7 @@ public class CMSSignedDataGenerator ASN1OctetString octs = null; - if (content != null) + if (content.getContent() != null) { ByteArrayOutputStream bOut = null; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSUtils.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSUtils.java index 1294251c8..eaaadf863 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSUtils.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/CMSUtils.java @@ -13,6 +13,7 @@ import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Set; +import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.BEROctetStringGenerator; import org.spongycastle.asn1.BERSet; import org.spongycastle.asn1.DERSet; @@ -27,6 +28,7 @@ import org.spongycastle.cert.X509CRLHolder; import org.spongycastle.cert.X509CertificateHolder; import org.spongycastle.operator.DigestCalculator; import org.spongycastle.util.Store; +import org.spongycastle.util.Strings; import org.spongycastle.util.io.Streams; import org.spongycastle.util.io.TeeInputStream; import org.spongycastle.util.io.TeeOutputStream; @@ -97,18 +99,35 @@ class CMSUtils static List getCRLsFromStore(Store crlStore) throws CMSException { - List certs = new ArrayList(); + List crls = new ArrayList(); try { for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();) { - X509CRLHolder c = (X509CRLHolder)it.next(); + Object rev = it.next(); - certs.add(c.toASN1Structure()); + if (rev instanceof X509CRLHolder) + { + X509CRLHolder c = (X509CRLHolder)rev; + + crls.add(c.toASN1Structure()); + } + else if (rev instanceof OtherRevocationInfoFormat) + { + OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev); + + validateInfoFormat(infoFormat); + + crls.add(new DERTaggedObject(false, 1, infoFormat)); + } + else if (rev instanceof ASN1TaggedObject) + { + crls.add(rev); + } } - return certs; + return crls; } catch (ClassCastException e) { @@ -116,6 +135,19 @@ class CMSUtils } } + private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat) + { + if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat())) + { + OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo()); + + if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL) + { + throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData"); + } + } + } + static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos) { List others = new ArrayList(); @@ -123,18 +155,11 @@ class CMSUtils for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();) { ASN1Encodable info = (ASN1Encodable)it.next(); + OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info); - if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(otherRevocationInfoFormat)) - { - OCSPResponse resp = OCSPResponse.getInstance(info); + validateInfoFormat(infoFormat); - if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL) - { - throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData"); - } - } - - others.add(new DERTaggedObject(false, 1, new OtherRevocationInfoFormat(otherRevocationInfoFormat, info))); + others.add(new DERTaggedObject(false, 1, infoFormat)); } return others; @@ -198,7 +223,64 @@ class CMSUtils throw new CMSException("Malformed content.", e); } } - + + static byte[] getPasswordBytes(int scheme, char[] password) + { + if (scheme == PasswordRecipient.PKCS5_SCHEME2) + { + return PKCS5PasswordToBytes(password); + } + + return PKCS5PasswordToUTF8Bytes(password); + } + + /** + * converts a password to a byte array according to the scheme in + * PKCS5 (ascii, no padding) + * + * @param password a character array representing the password. + * @return a byte array representing the password. + */ + private static byte[] PKCS5PasswordToBytes( + char[] password) + { + if (password != null) + { + byte[] bytes = new byte[password.length]; + + for (int i = 0; i != bytes.length; i++) + { + bytes[i] = (byte)password[i]; + } + + return bytes; + } + else + { + return new byte[0]; + } + } + + /** + * converts a password to a byte array according to the scheme in + * PKCS5 (UTF-8, no padding) + * + * @param password a character array representing the password. + * @return a byte array representing the password. + */ + private static byte[] PKCS5PasswordToUTF8Bytes( + char[] password) + { + if (password != null) + { + return Strings.toUTF8ByteArray(password); + } + else + { + return new byte[0]; + } + } + public static byte[] streamToByteArray( InputStream in) throws IOException diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java index 3fa4cf702..ab3628d50 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultAuthenticatedAttributeTableGenerator.java @@ -1,5 +1,6 @@ package org.spongycastle.cms; +import java.util.Enumeration; import java.util.Hashtable; import java.util.Map; @@ -57,7 +58,14 @@ public class DefaultAuthenticatedAttributeTableGenerator protected Hashtable createStandardAttributeTable( Map parameters) { - Hashtable std = (Hashtable)table.clone(); + Hashtable std = new Hashtable(); + + for (Enumeration en = table.keys(); en.hasMoreElements();) + { + Object key = en.nextElement(); + + std.put(key, table.get(key)); + } if (!std.containsKey(CMSAttributes.contentType)) { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java index 9a4f09226..1975968b5 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.bsi.BSIObjectIdentifiers; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.eac.EACObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; @@ -60,6 +61,12 @@ public class DefaultCMSSignatureAlgorithmNameGenerator addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA"); addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1"); addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1", "PLAIN-ECDSA"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224", "PLAIN-ECDSA"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256", "PLAIN-ECDSA"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384", "PLAIN-ECDSA"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512", "PLAIN-ECDSA"); + addEntries(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160", "PLAIN-ECDSA"); encryptionAlgs.put(X9ObjectIdentifiers.id_dsa, "DSA"); encryptionAlgs.put(PKCSObjectIdentifiers.rsaEncryption, "RSA"); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipient.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipient.java index b2762dd01..616f25ca6 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipient.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipient.java @@ -8,6 +8,9 @@ public interface PasswordRecipient public static final int PKCS5_SCHEME2 = 0; public static final int PKCS5_SCHEME2_UTF8 = 1; + byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException; + RecipientOperator getRecipientOperator(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] derivedKey, byte[] encryptedEncryptedContentKey) throws CMSException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInfoGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInfoGenerator.java index aa1b5a0b2..33c34b7aa 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInfoGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInfoGenerator.java @@ -12,9 +12,6 @@ import org.spongycastle.asn1.cms.RecipientInfo; import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.crypto.PBEParametersGenerator; -import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.operator.GenericKey; public abstract class PasswordRecipientInfoGenerator @@ -96,25 +93,9 @@ public abstract class PasswordRecipientInfoGenerator keyDerivationAlgorithm = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBKDF2, new PBKDF2Params(salt, 1024)); } - PBKDF2Params params = PBKDF2Params.getInstance(keyDerivationAlgorithm.getParameters()); - byte[] derivedKey; + byte[] encodedPassword = CMSUtils.getPasswordBytes(schemeID, password); - if (schemeID == PasswordRecipient.PKCS5_SCHEME2) - { - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); - - gen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), params.getSalt(), params.getIterationCount().intValue()); - - derivedKey = ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); - } - else - { - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); - - gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password), params.getSalt(), params.getIterationCount().intValue()); - - derivedKey = ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); - } + byte[] derivedKey = calculateDerivedKey(encodedPassword, keyDerivationAlgorithm, keySize); AlgorithmIdentifier kekAlgorithmId = new AlgorithmIdentifier(kekAlgorithm, new DEROctetString(iv)); @@ -133,6 +114,9 @@ public abstract class PasswordRecipientInfoGenerator keyEncryptionAlgorithm, encryptedKey)); } + protected abstract byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException; + protected abstract byte[] generateEncryptedBytes(AlgorithmIdentifier algorithm, byte[] derivedKey, GenericKey contentEncryptionKey) throws CMSException; } \ No newline at end of file diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInformation.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInformation.java index 90b7c4996..2c9efbac8 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInformation.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/PasswordRecipientInformation.java @@ -6,11 +6,7 @@ import java.util.Map; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.cms.PasswordRecipientInfo; -import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.crypto.PBEParametersGenerator; -import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.util.Integers; /** @@ -109,27 +105,12 @@ public class PasswordRecipientInformation AlgorithmIdentifier kekAlg = AlgorithmIdentifier.getInstance(info.getKeyEncryptionAlgorithm()); AlgorithmIdentifier kekAlgParams = AlgorithmIdentifier.getInstance(kekAlg.getParameters()); - byte[] passwordBytes = getPasswordBytes(pbeRecipient.getPasswordConversionScheme(), - pbeRecipient.getPassword()); - PBKDF2Params params = PBKDF2Params.getInstance(info.getKeyDerivationAlgorithm().getParameters()); - - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); - gen.init(passwordBytes, params.getSalt(), params.getIterationCount().intValue()); + byte[] passwordBytes = CMSUtils.getPasswordBytes(pbeRecipient.getPasswordConversionScheme(), pbeRecipient.getPassword()); int keySize = ((Integer)KEYSIZES.get(kekAlgParams.getAlgorithm())).intValue(); - byte[] derivedKey = ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + byte[] derivedKey = pbeRecipient.calculateDerivedKey(passwordBytes, this.getKeyDerivationAlgorithm(), keySize); return pbeRecipient.getRecipientOperator(kekAlgParams, messageAlgorithm, derivedKey, info.getEncryptedKey().getOctets()); } - - protected byte[] getPasswordBytes(int scheme, char[] password) - { - if (scheme == PasswordRecipient.PKCS5_SCHEME2) - { - return PBEParametersGenerator.PKCS5PasswordToBytes(password); - } - - return PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password); - } } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipient.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipient.java index 5317bb5ff..679f4144a 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipient.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipient.java @@ -1,11 +1,13 @@ package org.spongycastle.cms.bc; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipient; import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.Wrapper; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; @@ -49,6 +51,18 @@ public abstract class BcPasswordRecipient } } + public byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public int getPasswordConversionScheme() { return schemeID; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipientInfoGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipientInfoGenerator.java index c1559be79..4ea5cdfd5 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipientInfoGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/bc/BcPasswordRecipientInfoGenerator.java @@ -2,10 +2,12 @@ package org.spongycastle.cms.bc; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipientInfoGenerator; import org.spongycastle.crypto.Wrapper; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.operator.GenericKey; @@ -18,6 +20,18 @@ public class BcPasswordRecipientInfoGenerator super(kekAlgorithm, password); } + protected byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public byte[] generateEncryptedBytes(AlgorithmIdentifier keyEncryptionAlgorithm, byte[] derivedKey, GenericKey contentEncryptionKey) throws CMSException { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/CMSUtils.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/CMSUtils.java index a0a0812cb..9337a4246 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/CMSUtils.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/CMSUtils.java @@ -13,7 +13,7 @@ import org.spongycastle.asn1.x509.Certificate; import org.spongycastle.asn1.x509.Extension; import org.spongycastle.asn1.x509.TBSCertificateStructure; import org.spongycastle.cms.CMSException; -import org.spongycastle.jcajce.JcaJceUtils; +import org.spongycastle.jcajce.util.JcaJceUtils; class CMSUtils { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/DefaultJcaJceExtHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/DefaultJcaJceExtHelper.java index c0dfc3e80..1285ff078 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/DefaultJcaJceExtHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/DefaultJcaJceExtHelper.java @@ -5,7 +5,7 @@ import java.security.PrivateKey; import javax.crypto.SecretKey; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; import org.spongycastle.operator.SymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceSymmetricKeyUnwrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcaJceExtHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcaJceExtHelper.java index e4dd991c0..e29f1bd9b 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcaJceExtHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcaJceExtHelper.java @@ -5,7 +5,7 @@ import java.security.PrivateKey; import javax.crypto.SecretKey; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.JcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; import org.spongycastle.operator.SymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipient.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipient.java index 12f3a0673..b70651b1c 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipient.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipient.java @@ -9,9 +9,12 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipient; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.spongycastle.crypto.params.KeyParameter; /** * the RecipientInfo class for a recipient who has been sent a message @@ -70,6 +73,18 @@ public abstract class JcePasswordRecipient } } + public byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public int getPasswordConversionScheme() { return schemeID; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java index e96fd804f..d29fbab3e 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java @@ -10,9 +10,12 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipientInfoGenerator; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.operator.GenericKey; public class JcePasswordRecipientInfoGenerator @@ -39,6 +42,18 @@ public class JcePasswordRecipientInfoGenerator return this; } + protected byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public byte[] generateEncryptedBytes(AlgorithmIdentifier keyEncryptionAlgorithm, byte[] derivedKey, GenericKey contentEncryptionKey) throws CMSException { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/NamedJcaJceExtHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/NamedJcaJceExtHelper.java index ce24fe092..c55893203 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/NamedJcaJceExtHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/NamedJcaJceExtHelper.java @@ -5,7 +5,7 @@ import java.security.PrivateKey; import javax.crypto.SecretKey; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; import org.spongycastle.operator.SymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceSymmetricKeyUnwrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/ProviderJcaJceExtHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/ProviderJcaJceExtHelper.java index 7bb3c37c1..25075a1fa 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/ProviderJcaJceExtHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/cms/jcajce/ProviderJcaJceExtHelper.java @@ -6,7 +6,7 @@ import java.security.Provider; import javax.crypto.SecretKey; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.SymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceAsymmetricKeyUnwrapper; import org.spongycastle.operator.jcajce.JceSymmetricKeyUnwrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/eac/operator/jcajce/JcaEACSignatureVerifierBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/eac/operator/jcajce/JcaEACSignatureVerifierBuilder.java index 1d124cb23..7ffdb79af 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/eac/operator/jcajce/JcaEACSignatureVerifierBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/eac/operator/jcajce/JcaEACSignatureVerifierBuilder.java @@ -12,8 +12,8 @@ import java.security.Signature; import java.security.SignatureException; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.eac.EACObjectIdentifiers; import org.spongycastle.eac.operator.EACSignatureVerifier; @@ -116,8 +116,8 @@ public class JcaEACSignatureVerifierBuilder System.arraycopy(rawSign, len, s, 0, len); ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERInteger(new BigInteger(1, r))); - v.add(new DERInteger(new BigInteger(1, s))); + v.add(new ASN1Integer(new BigInteger(1, r))); + v.add(new ASN1Integer(new BigInteger(1, s))); DERSequence seq = new DERSequence(v); return seq.getEncoded(); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/MiscPEMGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/MiscPEMGenerator.java index 4f00d7aec..995bf7b5d 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/MiscPEMGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/MiscPEMGenerator.java @@ -8,7 +8,6 @@ import java.util.List; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.cms.ContentInfo; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -21,7 +20,6 @@ import org.spongycastle.cert.X509AttributeCertificateHolder; import org.spongycastle.cert.X509CRLHolder; import org.spongycastle.cert.X509CertificateHolder; import org.spongycastle.pkcs.PKCS10CertificationRequest; -import org.spongycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.spongycastle.util.Strings; import org.spongycastle.util.io.pem.PemGenerationException; import org.spongycastle.util.io.pem.PemHeader; @@ -105,16 +103,16 @@ public class MiscPEMGenerator DSAParameter p = DSAParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters()); ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERInteger(0)); - v.add(new DERInteger(p.getP())); - v.add(new DERInteger(p.getQ())); - v.add(new DERInteger(p.getG())); + v.add(new ASN1Integer(0)); + v.add(new ASN1Integer(p.getP())); + v.add(new ASN1Integer(p.getQ())); + v.add(new ASN1Integer(p.getG())); BigInteger x = ASN1Integer.getInstance(info.parsePrivateKey()).getValue(); BigInteger y = p.getG().modPow(x, p.getP()); - v.add(new DERInteger(y)); - v.add(new DERInteger(x)); + v.add(new ASN1Integer(y)); + v.add(new ASN1Integer(x)); encoding = new DERSequence(v).getEncoded(); } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMParser.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMParser.java index 91b1cff0b..bafe21269 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMParser.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMParser.java @@ -63,6 +63,7 @@ public class PEMParser parsers.put("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); parsers.put("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser()); parsers.put("CERTIFICATE", new X509CertificateParser()); + parsers.put("TRUSTED CERTIFICATE", new X509CertificateParser()); parsers.put("X509 CERTIFICATE", new X509CertificateParser()); parsers.put("X509 CRL", new X509CRLParser()); parsers.put("PKCS7", new PKCS7Parser()); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMUtilities.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMUtilities.java index 59f350060..e8fec527e 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMUtilities.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMUtilities.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.Set; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.util.Integers; @@ -48,7 +47,7 @@ public final class PEMUtilities return ((Integer)KEYSIZES.get(algorithm)).intValue(); } - static boolean isPKCS5Scheme1(DERObjectIdentifier algOid) + static boolean isPKCS5Scheme1(ASN1ObjectIdentifier algOid) { return PKCS5_SCHEME_1.contains(algOid); } @@ -58,7 +57,7 @@ public final class PEMUtilities return PKCS5_SCHEME_2.contains(algOid); } - public static boolean isPKCS12(DERObjectIdentifier algOid) + public static boolean isPKCS12(ASN1ObjectIdentifier algOid) { return algOid.getId().startsWith(PKCSObjectIdentifiers.pkcs_12PbeIds.getId()); } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMWriter.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMWriter.java index 2046d620a..379c014dc 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMWriter.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/PEMWriter.java @@ -10,6 +10,7 @@ import org.spongycastle.util.io.pem.PemWriter; /** * General purpose writer for OpenSSL PEM objects. + * @deprecated use JcaPEMWriter */ public class PEMWriter extends PemWriter @@ -24,6 +25,9 @@ public class PEMWriter super(out); } + /** + * @throws IOException + */ public void writeObject( Object obj) throws IOException @@ -31,6 +35,11 @@ public class PEMWriter writeObject(obj, null); } + /** + * @param obj + * @param encryptor + * @throws IOException + */ public void writeObject( Object obj, PEMEncryptor encryptor) diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMKeyConverter.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMKeyConverter.java index 8fa2b93ed..1b15639a0 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMKeyConverter.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMKeyConverter.java @@ -18,10 +18,10 @@ import org.spongycastle.asn1.pkcs.PrivateKeyInfo; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.openssl.PEMException; import org.spongycastle.openssl.PEMKeyPair; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMWriter.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMWriter.java new file mode 100644 index 000000000..0224b89e6 --- /dev/null +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcaPEMWriter.java @@ -0,0 +1,68 @@ +package org.spongycastle.openssl.jcajce; + +import java.io.IOException; +import java.io.Writer; + +import org.spongycastle.openssl.PEMEncryptor; +import org.spongycastle.util.io.pem.PemGenerationException; +import org.spongycastle.util.io.pem.PemObjectGenerator; +import org.spongycastle.util.io.pem.PemWriter; + +/** + * General purpose writer for OpenSSL PEM objects based on JCA/JCE classes. + */ +public class JcaPEMWriter + extends PemWriter +{ + /** + * Base constructor. + * + * @param out output stream to use. + */ + public JcaPEMWriter(Writer out) + { + super(out); + } + + /** + * @throws java.io.IOException + */ + public void writeObject( + Object obj) + throws IOException + { + writeObject(obj, null); + } + + /** + * @param obj + * @param encryptor + * @throws java.io.IOException + */ + public void writeObject( + Object obj, + PEMEncryptor encryptor) + throws IOException + { + try + { + super.writeObject(new JcaMiscPEMGenerator(obj, encryptor)); + } + catch (PemGenerationException e) + { + if (e.getCause() instanceof IOException) + { + throw (IOException)e.getCause(); + } + + throw e; + } + } + + public void writeObject( + PemObjectGenerator obj) + throws IOException + { + super.writeObject(obj); + } +} diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java index 2d8e45349..5050f4b2e 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java @@ -20,10 +20,10 @@ import org.spongycastle.asn1.pkcs.PBES2Parameters; import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.openssl.PEMException; import org.spongycastle.operator.InputDecryptor; import org.spongycastle.operator.InputDecryptorProvider; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java index 5cfb02b5f..8404661fd 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java @@ -28,10 +28,10 @@ import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorCreationException; import org.spongycastle.operator.OutputEncryptor; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMDecryptorProviderBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMDecryptorProviderBuilder.java index 2a260f236..b54d7fd30 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMDecryptorProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMDecryptorProviderBuilder.java @@ -2,10 +2,10 @@ package org.spongycastle.openssl.jcajce; import java.security.Provider; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.openssl.PEMDecryptor; import org.spongycastle.openssl.PEMDecryptorProvider; import org.spongycastle.openssl.PEMException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMEncryptorBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMEncryptorBuilder.java index 4a3f76477..3360f8a8a 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMEncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/JcePEMEncryptorBuilder.java @@ -3,10 +3,10 @@ package org.spongycastle.openssl.jcajce; import java.security.Provider; import java.security.SecureRandom; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.openssl.PEMEncryptor; import org.spongycastle.openssl.PEMException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/PEMUtilities.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/PEMUtilities.java index 050599dd8..6bfa2a575 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/PEMUtilities.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/openssl/jcajce/PEMUtilities.java @@ -14,14 +14,13 @@ import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.crypto.PBEParametersGenerator; import org.spongycastle.crypto.generators.OpenSSLPBEParametersGenerator; import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.jcajce.JcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; import org.spongycastle.openssl.EncryptionException; import org.spongycastle.openssl.PEMException; import org.spongycastle.util.Integers; @@ -63,7 +62,7 @@ class PEMUtilities return ((Integer)KEYSIZES.get(algorithm)).intValue(); } - static boolean isPKCS5Scheme1(DERObjectIdentifier algOid) + static boolean isPKCS5Scheme1(ASN1ObjectIdentifier algOid) { return PKCS5_SCHEME_1.contains(algOid); } @@ -73,7 +72,7 @@ class PEMUtilities return PKCS5_SCHEME_2.contains(algOid); } - public static boolean isPKCS12(DERObjectIdentifier algOid) + public static boolean isPKCS12(ASN1ObjectIdentifier algOid) { return algOid.getId().startsWith(PKCSObjectIdentifiers.pkcs_12PbeIds.getId()); } diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java index cd70901c5..58608c8ba 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java @@ -9,7 +9,9 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.bsi.BSIObjectIdentifiers; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.eac.EACObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; @@ -79,7 +81,17 @@ public class DefaultSignatureAlgorithmIdentifierFinder algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); - + algorithms.put("SHA1WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1); + algorithms.put("SHA224WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA224); + algorithms.put("SHA256WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA256); + algorithms.put("SHA384WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA384); + algorithms.put("SHA512WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_SHA512); + algorithms.put("RIPEMD160WITHPLAIN-ECDSA", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160); + algorithms.put("SHA1WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); + algorithms.put("SHA224WITHPCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); + algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); + algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384); + algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512); // // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. // The parameters field SHALL be NULL for RSA based signature algorithms. diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java index a796bbb89..f3a008ddf 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java @@ -10,9 +10,9 @@ import java.security.Signature; import java.security.SignatureException; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.ContentSigner; import org.spongycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java index 5db293186..7b5690e46 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java @@ -15,9 +15,9 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.cert.X509CertificateHolder; import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.ContentVerifier; import org.spongycastle.operator.ContentVerifierProvider; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java index 849126232..c734b8660 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JcaDigestCalculatorProviderBuilder.java @@ -7,9 +7,9 @@ import java.security.MessageDigest; import java.security.Provider; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.DigestCalculator; import org.spongycastle.operator.DigestCalculatorProvider; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java index fd70b040e..0b5cbf603 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java @@ -17,9 +17,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.AsymmetricKeyUnwrapper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyWrapper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyWrapper.java index 66d31b226..95eb3b9ac 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyWrapper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceAsymmetricKeyWrapper.java @@ -16,9 +16,9 @@ import javax.crypto.Cipher; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.AsymmetricKeyWrapper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyUnwrapper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyUnwrapper.java index 74ab54167..dd9e7e0a4 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyUnwrapper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyUnwrapper.java @@ -8,9 +8,9 @@ import javax.crypto.Cipher; import javax.crypto.SecretKey; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; import org.spongycastle.operator.SymmetricKeyUnwrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java index 55b2287a6..3689f6c23 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java @@ -15,9 +15,9 @@ import org.spongycastle.asn1.kisa.KISAObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.ntt.NTTObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; import org.spongycastle.operator.SymmetricKeyWrapper; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/OperatorHelper.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/OperatorHelper.java index 2a4ded274..8f2776aeb 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/OperatorHelper.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/operator/jcajce/OperatorHelper.java @@ -24,7 +24,9 @@ import javax.crypto.Cipher; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERNull; +import org.spongycastle.asn1.bsi.BSIObjectIdentifiers; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.eac.EACObjectIdentifiers; import org.spongycastle.asn1.kisa.KISAObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.ntt.NTTObjectIdentifiers; @@ -36,8 +38,8 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.cert.X509CertificateHolder; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.JcaJceUtils; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceUtils; import org.spongycastle.operator.OperatorCreationException; class OperatorHelper @@ -59,6 +61,17 @@ class OperatorHelper oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA"); oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA1, "SHA1WITHPLAIN-ECDSA"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA224, "SHA224WITHPLAIN-ECDSA"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA256, "SHA256WITHPLAIN-ECDSA"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA384, "SHA384WITHPLAIN-ECDSA"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_SHA512, "SHA512WITHPLAIN-ECDSA"); + oids.put(BSIObjectIdentifiers.ecdsa_plain_RIPEMD160, "RIPEMD160WITHPLAIN-ECDSA"); + oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1WITHCVC-ECDSA"); + oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224WITHCVC-ECDSA"); + oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256WITHCVC-ECDSA"); + oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384WITHCVC-ECDSA"); + oids.put(EACObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512WITHCVC-ECDSA"); oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); @@ -78,9 +91,9 @@ class OperatorHelper oids.put(NISTObjectIdentifiers.id_sha256, "SHA-256"); oids.put(NISTObjectIdentifiers.id_sha384, "SHA-384"); oids.put(NISTObjectIdentifiers.id_sha512, "SHA-512"); - oids.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD-128"); - oids.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD-160"); - oids.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD-256"); + oids.put(TeleTrusTObjectIdentifiers.ripemd128, "RIPEMD128"); + oids.put(TeleTrusTObjectIdentifiers.ripemd160, "RIPEMD160"); + oids.put(TeleTrusTObjectIdentifiers.ripemd256, "RIPEMD256"); asymmetricWrapperAlgNames.put(PKCSObjectIdentifiers.rsaEncryption, "RSA/ECB/PKCS1Padding"); @@ -229,7 +242,7 @@ class OperatorHelper try { - dig = helper.createDigest(getDigestAlgName(digAlgId.getAlgorithm())); + dig = helper.createDigest(JcaJceUtils.getDigestAlgName(digAlgId.getAlgorithm())); } catch (NoSuchAlgorithmException e) { @@ -323,7 +336,7 @@ class OperatorHelper if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params); - return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; + return JcaJceUtils.getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "WITHRSAANDMGF1"; } } @@ -335,55 +348,6 @@ class OperatorHelper return sigAlgId.getAlgorithm().getId(); } - private static String getDigestAlgName( - ASN1ObjectIdentifier digestAlgOID) - { - if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) - { - return "MD5"; - } - else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID)) - { - return "SHA1"; - } - else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID)) - { - return "SHA224"; - } - else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID)) - { - return "SHA256"; - } - else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID)) - { - return "SHA384"; - } - else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID)) - { - return "SHA512"; - } - else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID)) - { - return "RIPEMD128"; - } - else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID)) - { - return "RIPEMD160"; - } - else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID)) - { - return "RIPEMD256"; - } - else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID)) - { - return "GOST3411"; - } - else - { - return digestAlgOID.getId(); - } - } - public X509Certificate convertCertificate(X509CertificateHolder certHolder) throws CertificateException { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcaPKCS10CertificationRequest.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcaPKCS10CertificationRequest.java index 3e4e6dc0e..8f0e20cf7 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcaPKCS10CertificationRequest.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcaPKCS10CertificationRequest.java @@ -15,10 +15,10 @@ import org.spongycastle.asn1.pkcs.CertificationRequest; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.pkcs.PKCS10CertificationRequest; public class JcaPKCS10CertificationRequest diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java index 4e6b39f0f..25b8da06e 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilder.java @@ -17,11 +17,11 @@ import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.crypto.ExtendedDigest; import org.spongycastle.crypto.generators.PKCS12ParametersGenerator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; import org.spongycastle.jcajce.io.MacOutputStream; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.MacCalculator; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java index 413afeec8..6c9c30231 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCS12MacCalculatorBuilderProvider.java @@ -14,11 +14,11 @@ import org.spongycastle.asn1.DERNull; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.crypto.generators.PKCS12ParametersGenerator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; import org.spongycastle.jcajce.io.MacOutputStream; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.MacCalculator; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java index 846417382..5f5413caa 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEInputDecryptorProviderBuilder.java @@ -20,13 +20,13 @@ import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.spongycastle.jcajce.spec.GOST28147ParameterSpec; import org.spongycastle.jcajce.spec.PBKDF2KeySpec; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.DefaultSecretKeySizeProvider; import org.spongycastle.operator.InputDecryptor; import org.spongycastle.operator.InputDecryptorProvider; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java index ebf49c5e3..9ab806efa 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/pkcs/jcajce/JcePKCSPBEOutputEncryptorBuilder.java @@ -22,10 +22,10 @@ import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.crypto.PBEParametersGenerator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.DefaultSecretKeySizeProvider; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/GenTimeAccuracy.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/GenTimeAccuracy.java index 0932f3eec..bb042e90f 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/GenTimeAccuracy.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/GenTimeAccuracy.java @@ -1,6 +1,6 @@ package org.spongycastle.tsp; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.tsp.Accuracy; public class GenTimeAccuracy @@ -28,7 +28,7 @@ public class GenTimeAccuracy } private int getTimeComponent( - DERInteger time) + ASN1Integer time) { if (time != null) { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampRequest.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampRequest.java index 55349960e..54ed40ec4 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampRequest.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampRequest.java @@ -14,7 +14,6 @@ import java.util.Set; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cmp.PKIFailureInfo; import org.spongycastle.asn1.tsp.TimeStampReq; import org.spongycastle.asn1.x509.Extension; @@ -162,7 +161,7 @@ public class TimeStampRequest Enumeration en = this.getExtensions().oids(); while(en.hasMoreElements()) { - String oid = ((DERObjectIdentifier)en.nextElement()).getId(); + String oid = ((ASN1ObjectIdentifier)en.nextElement()).getId(); if (!extensions.contains(oid)) { throw new TSPValidationException("request contains unknown extension.", PKIFailureInfo.unacceptedExtension); diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampResponseGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampResponseGenerator.java index efe08a50a..57e83aa2e 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampResponseGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampResponseGenerator.java @@ -8,9 +8,9 @@ import java.util.Iterator; import java.util.Set; import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.DERUTF8String; import org.spongycastle.asn1.cmp.PKIFailureInfo; @@ -119,7 +119,7 @@ public class TimeStampResponseGenerator { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERInteger(status)); + v.add(new ASN1Integer(status)); if (statusStrings.size() > 0) { diff --git a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java index 71b1cda91..f3783f80c 100644 --- a/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java +++ b/extern/spongycastle/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java @@ -4,7 +4,10 @@ import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -83,6 +86,7 @@ public class TimeStampTokenGenerator private List certs = new ArrayList(); private List crls = new ArrayList(); private List attrCerts = new ArrayList(); + private Map otherRevoc = new HashMap(); private SignerInfoGenerator signerInfoGen; /** @@ -228,6 +232,19 @@ public class TimeStampTokenGenerator attrCerts.addAll(attrStore.getMatches(null)); } + /** + * Add a Store of otherRevocationData to the CRL set to be included with the generated TimeStampToken. + * + * @param otherRevocationInfoFormat the OID specifying the format of the otherRevocationInfo data. + * @param otherRevocationInfos a Store of otherRevocationInfo data to add. + */ + public void addOtherRevocationInfo( + ASN1ObjectIdentifier otherRevocationInfoFormat, + Store otherRevocationInfos) + { + otherRevoc.put(otherRevocationInfoFormat, otherRevocationInfos.getMatches(null)); + } + public void setAccuracySeconds(int accuracySeconds) { this.accuracySeconds = accuracySeconds; @@ -328,12 +345,19 @@ public class TimeStampTokenGenerator { // TODO: do we need to check certs non-empty? signedDataGenerator.addCertificates(new CollectionStore(certs)); - signedDataGenerator.addCRLs(new CollectionStore(crls)); signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts)); } - else + + signedDataGenerator.addCRLs(new CollectionStore(crls)); + + if (!otherRevoc.isEmpty()) { - signedDataGenerator.addCRLs(new CollectionStore(crls)); + for (Iterator it = otherRevoc.keySet().iterator(); it.hasNext();) + { + ASN1ObjectIdentifier format = (ASN1ObjectIdentifier)it.next(); + + signedDataGenerator.addOtherRevocationInfo(format, new CollectionStore((Collection)otherRevoc.get(format))); + } } signedDataGenerator.addSignerInfoGenerator(signerInfoGen); diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java new file mode 100644 index 000000000..eec071e14 --- /dev/null +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java @@ -0,0 +1,134 @@ +package org.spongycastle.cert.crmf.bc; + +import java.security.SecureRandom; + +import org.spongycastle.cert.crmf.EncryptedValuePadder; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.crypto.generators.MGF1BytesGenerator; +import org.spongycastle.crypto.params.MGFParameters; + +/** + * An encrypted value padder that uses MGF1 as the basis of the padding. + */ +public class BcFixedLengthMGF1Padder + implements EncryptedValuePadder +{ + private int length; + private SecureRandom random; + private Digest dig = new SHA1Digest(); + + /** + * Create a padder to so that padded output will always be at least + * length bytes long. + * + * @param length fixed length for padded output. + */ + public BcFixedLengthMGF1Padder(int length) + { + this(length, null); + } + + /** + * Create a padder to so that padded output will always be at least + * length bytes long, using the passed in source of randomness to + * provide the random material for the padder. + * + * @param length fixed length for padded output. + * @param random a source of randomness. + */ + public BcFixedLengthMGF1Padder(int length, SecureRandom random) + { + this.length = length; + this.random = random; + } + + public byte[] getPaddedData(byte[] data) + { + byte[] bytes = new byte[length]; + byte[] seed = new byte[dig.getDigestSize()]; + byte[] mask = new byte[length - dig.getDigestSize()]; + + if (random == null) + { + random = new SecureRandom(); + } + + random.nextBytes(seed); + + MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig); + + maskGen.init(new MGFParameters(seed)); + + maskGen.generateBytes(mask, 0, mask.length); + + System.arraycopy(seed, 0, bytes, 0, seed.length); + System.arraycopy(data, 0, bytes, seed.length, data.length); + + for (int i = seed.length + data.length + 1; i != bytes.length; i++) + { + bytes[i] = (byte)(1 + nextByte(random)); + } + + for (int i = 0; i != mask.length; i++) + { + bytes[i + seed.length] ^= mask[i]; + } + + return bytes; + } + + public byte[] getUnpaddedData(byte[] paddedData) + { + byte[] seed = new byte[dig.getDigestSize()]; + byte[] mask = new byte[length - dig.getDigestSize()]; + + System.arraycopy(paddedData, 0, seed, 0, seed.length); + + MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig); + + maskGen.init(new MGFParameters(seed)); + + maskGen.generateBytes(mask, 0, mask.length); + + for (int i = 0; i != mask.length; i++) + { + paddedData[i + seed.length] ^= mask[i]; + } + + int end = 0; + + for (int i = paddedData.length - 1; i != seed.length; i--) + { + if (paddedData[i] == 0) + { + end = i; + break; + } + } + + if (end == 0) + { + throw new IllegalStateException("bad padding in encoding"); + } + + byte[] data = new byte[end - seed.length]; + + System.arraycopy(paddedData, seed.length, data, 0, data.length); + + return data; + } + + private int nextByte(SecureRandom random) + { + int bits, val; + do + { + bits = random.nextInt() & 0x7fffffff; + val = bits % 255; + } + while (bits - val + 254 < 0); + + return val; + } +} diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java index c11e55f0d..afed75903 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java @@ -44,7 +44,7 @@ import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cms.CMSAlgorithm; import org.spongycastle.cms.CMSEnvelopedDataGenerator; -import org.spongycastle.jcajce.JcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; class CRMFHelper { diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java index e06e249fa..0cf875090 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java @@ -1,7 +1,6 @@ package org.spongycastle.cert.crmf.jcajce; import java.io.InputStream; -import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.Key; import java.security.PrivateKey; @@ -18,9 +17,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.ValueDecryptorGenerator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.InputDecryptor; public class JceAsymmetricValueDecryptorGenerator diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java index 6b8e0d2ac..5be72f2a8 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java @@ -15,9 +15,9 @@ import javax.crypto.SecretKey; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OutputEncryptor; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java index 4aaff8618..6c5937096 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java @@ -1,6 +1,5 @@ package org.spongycastle.cert.crmf.jcajce; -import java.security.GeneralSecurityException; import java.security.MessageDigest; import java.security.Provider; import java.security.InvalidKeyException; @@ -11,9 +10,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.PKMACValuesCalculator; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; public class JcePKMACValuesCalculator implements PKMACValuesCalculator diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipient.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipient.java index 0572364bf..31e8729b3 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipient.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipient.java @@ -1,19 +1,22 @@ package org.spongycastle.cms.jcajce; -import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; import java.security.Key; import java.security.Provider; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipient; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.spongycastle.crypto.params.KeyParameter; /** * the RecipientInfo class for a recipient who has been sent a message @@ -74,12 +77,24 @@ public abstract class JcePasswordRecipient { throw new CMSException("cannot process content encryption key: " + e.getMessage(), e); } - catch (GeneralSecurityException e) + catch (InvalidAlgorithmParameterException e) { throw new CMSException("cannot process content encryption key: " + e.getMessage(), e); } } + public byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public int getPasswordConversionScheme() { return schemeID; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java index e1306fd9e..ae706b10e 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java @@ -1,9 +1,9 @@ package org.spongycastle.cms.jcajce; import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; import java.security.Key; import java.security.Provider; -import java.security.InvalidKeyException; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; @@ -11,9 +11,12 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cms.CMSException; import org.spongycastle.cms.PasswordRecipientInfoGenerator; +import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.operator.GenericKey; public class JcePasswordRecipientInfoGenerator @@ -40,6 +43,18 @@ public class JcePasswordRecipientInfoGenerator return this; } + protected byte[] calculateDerivedKey(byte[] encodedPassword, AlgorithmIdentifier derivationAlgorithm, int keySize) + throws CMSException + { + PBKDF2Params params = PBKDF2Params.getInstance(derivationAlgorithm.getParameters()); + + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(); + + gen.init(encodedPassword, params.getSalt(), params.getIterationCount().intValue()); + + return ((KeyParameter)gen.generateDerivedParameters(keySize)).getKey(); + } + public byte[] generateEncryptedBytes(AlgorithmIdentifier keyEncryptionAlgorithm, byte[] derivedKey, GenericKey contentEncryptionKey) throws CMSException { @@ -54,11 +69,11 @@ public class JcePasswordRecipientInfoGenerator return keyEncryptionCipher.wrap(contentEncryptionKeySpec); } - catch (InvalidKeyException e) + catch (GeneralSecurityException e) { throw new CMSException("cannot process content encryption key: " + e.getMessage(), e); } - catch (GeneralSecurityException e) + catch (InvalidKeyException e) { throw new CMSException("cannot process content encryption key: " + e.getMessage(), e); } diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java index 22c8c3de3..bd0e93f26 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8DecryptorProviderBuilder.java @@ -23,10 +23,10 @@ import org.spongycastle.asn1.pkcs.PBES2Parameters; import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.openssl.PEMException; import org.spongycastle.operator.InputDecryptor; import org.spongycastle.operator.InputDecryptorProvider; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java index 60b715d45..139d6fcc2 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/openssl/jcajce/JceOpenSSLPKCS8EncryptorBuilder.java @@ -31,10 +31,10 @@ import org.spongycastle.asn1.pkcs.PBKDF2Params; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.JcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorCreationException; import org.spongycastle.operator.OutputEncryptor; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java index f677e3f93..9f88073e6 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentSignerBuilder.java @@ -2,7 +2,6 @@ package org.spongycastle.operator.jcajce; import java.io.IOException; import java.io.OutputStream; -import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.Provider; @@ -11,10 +10,9 @@ import java.security.Signature; import java.security.SignatureException; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.ContentSigner; import org.spongycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java index fe44d94e3..82ddae47d 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java @@ -2,7 +2,6 @@ package org.spongycastle.operator.jcajce; import java.io.IOException; import java.io.OutputStream; -import java.security.GeneralSecurityException; import java.security.Provider; import java.security.PublicKey; import java.security.Signature; @@ -15,9 +14,9 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.cert.X509CertificateHolder; import org.spongycastle.cert.jcajce.JcaX509CertificateHolder; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.ContentVerifier; import org.spongycastle.operator.ContentVerifierProvider; import org.spongycastle.operator.OperatorCreationException; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java index 3cf379a2b..29f7fb3d1 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java @@ -1,6 +1,5 @@ package org.spongycastle.operator.jcajce; -import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Key; @@ -17,9 +16,9 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.AsymmetricKeyUnwrapper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java index 4f5818246..2fd2f97cd 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/JceSymmetricKeyWrapper.java @@ -9,16 +9,16 @@ import java.security.InvalidKeyException; import javax.crypto.Cipher; import javax.crypto.SecretKey; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.kisa.KISAObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.ntt.NTTObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OperatorException; import org.spongycastle.operator.SymmetricKeyWrapper; @@ -87,18 +87,18 @@ public class JceSymmetricKeyWrapper if (algorithm.startsWith("DES")) { - return new AlgorithmIdentifier(new DERObjectIdentifier( + return new AlgorithmIdentifier(new ASN1ObjectIdentifier( "1.2.840.113549.1.9.16.3.6"), new DERNull()); } else if (algorithm.startsWith("RC2")) { - return new AlgorithmIdentifier(new DERObjectIdentifier( - "1.2.840.113549.1.9.16.3.7"), new DERInteger(58)); + return new AlgorithmIdentifier(new ASN1ObjectIdentifier( + "1.2.840.113549.1.9.16.3.7"), new ASN1Integer(58)); } else if (algorithm.startsWith("AES")) { int length = key.getEncoded().length * 8; - DERObjectIdentifier wrapOid; + ASN1ObjectIdentifier wrapOid; if (length == 128) { @@ -128,7 +128,7 @@ public class JceSymmetricKeyWrapper else if (algorithm.startsWith("Camellia")) { int length = key.getEncoded().length * 8; - DERObjectIdentifier wrapOid; + ASN1ObjectIdentifier wrapOid; if (length == 128) { diff --git a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/OperatorHelper.java b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/OperatorHelper.java index 25aaefd38..8507d8784 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/OperatorHelper.java +++ b/extern/spongycastle/pkix/src/main/jdk1.1/org/spongycastle/operator/jcajce/OperatorHelper.java @@ -36,8 +36,7 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.cert.X509CertificateHolder; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.JcaJceUtils; +import org.spongycastle.jcajce.util.JcaJceHelper; import org.spongycastle.operator.OperatorCreationException; class OperatorHelper diff --git a/extern/spongycastle/pkix/src/main/jdk1.2/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/extern/spongycastle/pkix/src/main/jdk1.2/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java index 1a1114561..c3970ee68 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.2/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java +++ b/extern/spongycastle/pkix/src/main/jdk1.2/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java @@ -14,9 +14,9 @@ import javax.crypto.SecretKey; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.cert.crmf.CRMFException; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; import org.spongycastle.operator.GenericKey; import org.spongycastle.operator.OutputEncryptor; diff --git a/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java index abbf964ad..eac007e0d 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java +++ b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/crmf/jcajce/JcaCertificateRequestMessage.java @@ -7,9 +7,9 @@ import org.spongycastle.asn1.crmf.CertReqMsg; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.cert.crmf.CRMFException; import org.spongycastle.cert.crmf.CertificateRequestMessage; -import org.spongycastle.jcajce.DefaultJcaJceHelper; -import org.spongycastle.jcajce.NamedJcaJceHelper; -import org.spongycastle.jcajce.ProviderJcaJceHelper; +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; public class JcaCertificateRequestMessage extends CertificateRequestMessage diff --git a/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java new file mode 100644 index 000000000..f40ab480f --- /dev/null +++ b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/cert/jcajce/JcaX509ExtensionUtils.java @@ -0,0 +1,138 @@ +package org.spongycastle.cert.jcajce; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; + +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; +import org.spongycastle.asn1.x509.GeneralName; +import org.spongycastle.asn1.x509.GeneralNames; +import org.spongycastle.asn1.x509.SubjectKeyIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.cert.X509ExtensionUtils; +import org.spongycastle.operator.DigestCalculator; + +public class JcaX509ExtensionUtils + extends X509ExtensionUtils +{ + /** + * Create a utility class pre-configured with a SHA-1 digest calculator based on the + * default implementation. + * + * @throws java.security.NoSuchAlgorithmException + */ + public JcaX509ExtensionUtils() + throws NoSuchAlgorithmException + { + super(new SHA1DigestCalculator(MessageDigest.getInstance("SHA1"))); + } + + public JcaX509ExtensionUtils(DigestCalculator calculator) + { + super(calculator); + } + + public AuthorityKeyIdentifier createAuthorityKeyIdentifier( + X509Certificate cert) + throws CertificateEncodingException + { + return super.createAuthorityKeyIdentifier(new JcaX509CertificateHolder(cert)); + } + + public AuthorityKeyIdentifier createAuthorityKeyIdentifier( + PublicKey pubKey) + { + return super.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded())); + } + + public AuthorityKeyIdentifier createAuthorityKeyIdentifier(PublicKey pubKey, GeneralNames generalNames, BigInteger serial) + { + return super.createAuthorityKeyIdentifier(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()), generalNames, serial); + } + + /** + * Return a RFC 3280 type 1 key identifier. As in: + *+ * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the + * value of the BIT STRING subjectPublicKey (excluding the tag, + * length, and number of unused bits). + *+ * @param publicKey the key object containing the key identifier is to be based on. + * @return the key identifier. + */ + public SubjectKeyIdentifier createSubjectKeyIdentifier( + PublicKey publicKey) + { + return super.createSubjectKeyIdentifier(SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); + } + + /** + * Return a RFC 3280 type 2 key identifier. As in: + *+ * (2) The keyIdentifier is composed of a four bit type field with + * the value 0100 followed by the least significant 60 bits of the + * SHA-1 hash of the value of the BIT STRING subjectPublicKey. + *+ * @param publicKey the key object of interest. + * @return the key identifier. + */ + public SubjectKeyIdentifier createTruncatedSubjectKeyIdentifier(PublicKey publicKey) + { + return super.createSubjectKeyIdentifier(SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); + } + + /** + * Return the ASN.1 object contained in a byte[] returned by a getExtensionValue() call. + * + * @param encExtValue DER encoded OCTET STRING containing the DER encoded extension object. + * @return an ASN.1 object + * @throws java.io.IOException on a parsing error. + */ + public static ASN1Primitive parseExtensionValue(byte[] encExtValue) + throws IOException + { + return ASN1Primitive.fromByteArray(ASN1OctetString.getInstance(encExtValue).getOctets()); + } + + private static class SHA1DigestCalculator + implements DigestCalculator + { + private ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + private MessageDigest digest; + + public SHA1DigestCalculator(MessageDigest digest) + { + this.digest = digest; + } + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1); + } + + public OutputStream getOutputStream() + { + return bOut; + } + + public byte[] getDigest() + { + byte[] bytes = digest.digest(bOut.toByteArray()); + + bOut.reset(); + + return bytes; + } + } +} diff --git a/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/operator/jcajce/OperatorHelper.java b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/operator/jcajce/OperatorHelper.java index 135e59655..419f0939e 100644 --- a/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/operator/jcajce/OperatorHelper.java +++ b/extern/spongycastle/pkix/src/main/jdk1.3/org/spongycastle/operator/jcajce/OperatorHelper.java @@ -36,8 +36,7 @@ import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; import org.spongycastle.cert.X509CertificateHolder; -import org.spongycastle.jcajce.JcaJceHelper; -import org.spongycastle.jcajce.JcaJceUtils; +import org.spongycastle.jcajce.util.JcaJceHelper; import org.spongycastle.operator.OperatorCreationException; class OperatorHelper diff --git a/extern/spongycastle/prov/build.gradle b/extern/spongycastle/prov/build.gradle index 1cf3c8fd8..8edc0afb3 100644 --- a/extern/spongycastle/prov/build.gradle +++ b/extern/spongycastle/prov/build.gradle @@ -6,4 +6,4 @@ dependencies { sourceCompatibility = 1.5 targetCompatibility = 1.5 -version = '1.50.0.0' +version = '1.51.0.0' diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceUtils.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceUtils.java deleted file mode 100644 index 8a9f202dd..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.spongycastle.jcajce; - -import java.io.IOException; -import java.security.AlgorithmParameters; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1Primitive; - -public class JcaJceUtils -{ - private JcaJceUtils() - { - - } - - /** - * Extract an ASN.1 encodable from an AlgorithmParameters object. - * - * @param params the object to get the encoding used to create the return value. - * @return an ASN.1 object representing the primitives making up the params parameter. - * @throws IOException if an encoding cannot be extracted. - */ - public static ASN1Encodable extractParameters(AlgorithmParameters params) - throws IOException - { - // we try ASN.1 explicitly first just in case and then role back to the default. - ASN1Encodable asn1Params; - try - { - asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1")); - } - catch (Exception ex) - { - asn1Params = ASN1Primitive.fromByteArray(params.getEncoded()); - } - - return asn1Params; - } - - public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams) - throws IOException - { - // we try ASN.1 explicitly first just in case and then role back to the default. - try - { - params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1"); - } - catch (Exception ex) - { - params.init(sParams.toASN1Primitive().getEncoded()); - } - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/DH.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/DH.java index 86ee0eaaf..e14ec8018 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/DH.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/DH.java @@ -1,5 +1,8 @@ package org.spongycastle.jcajce.provider.asymmetric; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.jcajce.provider.asymmetric.dh.KeyFactorySpi; import org.spongycastle.jcajce.provider.config.ConfigurableProvider; import org.spongycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; @@ -36,6 +39,9 @@ public class DH provider.addAlgorithm("Cipher.DHIESwithAES", PREFIX + "IESCipher$IESwithAES"); provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES"); provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede"); + + registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", new KeyFactorySpi()); + registerOid(provider, X9ObjectIdentifiers.dhpublicnumber, "DH", new KeyFactorySpi()); } } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/EC.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/EC.java index ff043d15d..178a301ee 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/EC.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/EC.java @@ -1,5 +1,6 @@ package org.spongycastle.jcajce.provider.asymmetric; +import org.spongycastle.asn1.bsi.BSIObjectIdentifiers; import org.spongycastle.asn1.eac.EACObjectIdentifiers; import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.spongycastle.asn1.x9.X9ObjectIdentifiers; @@ -25,6 +26,7 @@ public class EC provider.addAlgorithm("KeyAgreement.ECMQV", PREFIX + "KeyAgreementSpi$MQV"); provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDF"); provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$MQVwithSHA1KDF"); + provider.addAlgorithm("KeyAgreement.ECDHWITHSHA1KDF", PREFIX + "KeyAgreementSpi$DHwithSHA1KDF"); registerOid(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC", new KeyFactorySpi.EC()); // TODO Should this be an alias for ECDH? @@ -45,6 +47,7 @@ public class EC provider.addAlgorithm("KeyPairGenerator.EC", PREFIX + "KeyPairGeneratorSpi$EC"); provider.addAlgorithm("KeyPairGenerator.ECDSA", PREFIX + "KeyPairGeneratorSpi$ECDSA"); provider.addAlgorithm("KeyPairGenerator.ECDH", PREFIX + "KeyPairGeneratorSpi$ECDH"); + provider.addAlgorithm("KeyPairGenerator.ECDHWITHSHA1KDF", PREFIX + "KeyPairGeneratorSpi$ECDH"); provider.addAlgorithm("KeyPairGenerator.ECDHC", PREFIX + "KeyPairGeneratorSpi$ECDHC"); provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH"); provider.addAlgorithm("KeyPairGenerator.ECMQV", PREFIX + "KeyPairGeneratorSpi$ECMQV"); @@ -54,6 +57,10 @@ public class EC provider.addAlgorithm("Cipher.ECIESWITHAES", PREFIX + "IESCipher$ECIESwithAES"); provider.addAlgorithm("Cipher.ECIESwithDESEDE", PREFIX + "IESCipher$ECIESwithDESede"); provider.addAlgorithm("Cipher.ECIESWITHDESEDE", PREFIX + "IESCipher$ECIESwithDESede"); + provider.addAlgorithm("Cipher.ECIESwithAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC"); + provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC"); + provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); + provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA"); provider.addAlgorithm("Signature.NONEwithECDSA", PREFIX + "SignatureSpi$ecDSAnone"); @@ -91,6 +98,13 @@ public class EC addSignatureAlgorithm(provider, "SHA256", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); addSignatureAlgorithm(provider, "SHA384", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", EACObjectIdentifiers.id_TA_ECDSA_SHA_384); addSignatureAlgorithm(provider, "SHA512", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", EACObjectIdentifiers.id_TA_ECDSA_SHA_512); + + addSignatureAlgorithm(provider, "SHA1", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA", BSIObjectIdentifiers.ecdsa_plain_SHA1); + addSignatureAlgorithm(provider, "SHA224", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA224", BSIObjectIdentifiers.ecdsa_plain_SHA224); + addSignatureAlgorithm(provider, "SHA256", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", BSIObjectIdentifiers.ecdsa_plain_SHA256); + addSignatureAlgorithm(provider, "SHA384", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", BSIObjectIdentifiers.ecdsa_plain_SHA384); + addSignatureAlgorithm(provider, "SHA512", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", BSIObjectIdentifiers.ecdsa_plain_SHA512); + addSignatureAlgorithm(provider, "RIPEMD160", "PLAIN-ECDSA", PREFIX + "SignatureSpi$ecPlainDSARP160", BSIObjectIdentifiers.ecdsa_plain_RIPEMD160); } } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/RSA.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/RSA.java index 266c094bb..5087d1ee3 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/RSA.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/RSA.java @@ -80,6 +80,10 @@ public class RSA provider.addAlgorithm("Signature." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA"); provider.addAlgorithm("Signature.OID." + PKCSObjectIdentifiers.id_RSASSA_PSS, PREFIX + "PSSSignatureSpi$PSSwithRSA"); + provider.addAlgorithm("Signature.SHA224WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA224withRSA"); + provider.addAlgorithm("Signature.SHA256WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA256withRSA"); + provider.addAlgorithm("Signature.SHA384WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA384withRSA"); + provider.addAlgorithm("Signature.SHA512WITHRSAANDMGF1", PREFIX + "PSSSignatureSpi$SHA512withRSA"); provider.addAlgorithm("Signature.SHA224withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA224withRSA"); provider.addAlgorithm("Signature.SHA256withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA256withRSA"); provider.addAlgorithm("Signature.SHA384withRSA/PSS", PREFIX + "PSSSignatureSpi$SHA384withRSA"); @@ -101,10 +105,6 @@ public class RSA provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSAandMGF1", "SHA256withRSA/PSS"); provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSAandMGF1", "SHA384withRSA/PSS"); provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSAandMGF1", "SHA512withRSA/PSS"); - provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHRSAANDMGF1", "SHA224withRSA/PSS"); - provider.addAlgorithm("Alg.Alias.Signature.SHA256WITHRSAANDMGF1", "SHA256withRSA/PSS"); - provider.addAlgorithm("Alg.Alias.Signature.SHA384WITHRSAANDMGF1", "SHA384withRSA/PSS"); - provider.addAlgorithm("Alg.Alias.Signature.SHA512WITHRSAANDMGF1", "SHA512withRSA/PSS"); if (provider.hasAlgorithm("MessageDigest", "MD2")) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java index ecad1e87e..c67c417f6 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java @@ -34,9 +34,9 @@ public class KeyPairGeneratorSpi int strength, SecureRandom random) { - if (strength < 512 || strength > 1024 || strength % 64 != 0) + if (strength < 512 || strength > 4096 || ((strength < 1024) && strength % 64 != 0) || (strength >= 1024 && strength % 1024 != 0)) { - throw new InvalidParameterException("strength must be from 512 - 1024 and a multiple of 64"); + throw new InvalidParameterException("strength must be from 512 - 4096 and a multiple of 1024 above 1024"); } this.strength = strength; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java index ac595e20b..2a70970d4 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PrivateKey.java @@ -13,12 +13,11 @@ import java.util.Enumeration; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; import org.spongycastle.asn1.ua.DSTU4145NamedCurves; import org.spongycastle.asn1.ua.UAObjectIdentifiers; @@ -244,9 +243,9 @@ public class BCDSTU4145PrivateKey } ASN1Encodable privKey = info.parsePrivateKey(); - if (privKey instanceof DERInteger) + if (privKey instanceof ASN1Integer) { - DERInteger derD = DERInteger.getInstance(privKey); + ASN1Integer derD = ASN1Integer.getInstance(privKey); this.d = derD.getValue(); } @@ -286,10 +285,10 @@ public class BCDSTU4145PrivateKey if (ecSpec instanceof ECNamedCurveSpec) { - DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); if (curveOid == null) // guess it's the OID { - curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); } params = new X962Parameters(curveOid); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java index e2c1aed8d..891c39da5 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/dstu/BCDSTU4145PublicKey.java @@ -36,6 +36,8 @@ import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.jce.spec.ECNamedCurveParameterSpec; import org.spongycastle.jce.spec.ECNamedCurveSpec; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.custom.sec.SecP256K1Point; +import org.spongycastle.math.ec.custom.sec.SecP256R1Point; public class BCDSTU4145PublicKey implements ECPublicKey, org.spongycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -352,14 +354,7 @@ public class BCDSTU4145PublicKey { if (ecSpec == null) { - if (q instanceof org.spongycastle.math.ec.ECPoint.Fp) - { - return new org.spongycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord()); - } - else - { - return new org.spongycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord()); - } + return q.getDetachedPoint(); } return q; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index d1bc1d800..482776dfc 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -34,6 +34,8 @@ import org.spongycastle.jce.interfaces.ECPointEncoder; import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.jce.spec.ECNamedCurveSpec; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.custom.sec.SecP256K1Point; +import org.spongycastle.math.ec.custom.sec.SecP256R1Point; public class BCECPublicKey implements ECPublicKey, org.spongycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -82,6 +84,8 @@ public class BCECPublicKey ECCurve curve = spec.getParams().getCurve(); EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); + // this may seem a little long-winded but it's how we pick up the custom curve. + this.q = EC5Util.convertCurve(ellipticCurve).createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()); this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); } else @@ -132,7 +136,6 @@ public class BCECPublicKey ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; - this.q = params.getQ(); if (spec == null) { @@ -147,6 +150,8 @@ public class BCECPublicKey this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); } + this.q = EC5Util.convertCurve(ecSpec.getCurve()).createPoint(params.getQ().getAffineXCoord().toBigInteger(), params.getQ().getAffineYCoord().toBigInteger()); + this.configuration = configuration; } @@ -369,14 +374,7 @@ public class BCECPublicKey { if (ecSpec == null) { - if (q instanceof org.spongycastle.math.ec.ECPoint.Fp) - { - return new org.spongycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord()); - } - else - { - return new org.spongycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord()); - } + return q.getDetachedPoint(); } return q; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/IESCipher.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/IESCipher.java index 39baf08ff..69b614958 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/IESCipher.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/IESCipher.java @@ -18,6 +18,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; +import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.KeyEncoder; import org.spongycastle.crypto.agreement.ECDHBasicAgreement; @@ -29,14 +30,15 @@ import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator; import org.spongycastle.crypto.generators.KDF2BytesGenerator; import org.spongycastle.crypto.macs.HMac; +import org.spongycastle.crypto.modes.CBCBlockCipher; import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; -import org.spongycastle.crypto.params.IESParameters; import org.spongycastle.crypto.params.IESWithCipherParameters; +import org.spongycastle.crypto.params.ParametersWithIV; import org.spongycastle.crypto.parsers.ECIESPublicKeyParser; import org.spongycastle.jcajce.provider.asymmetric.util.ECUtil; import org.spongycastle.jcajce.provider.asymmetric.util.IESUtil; @@ -52,6 +54,7 @@ import org.spongycastle.util.Strings; public class IESCipher extends CipherSpi { + private int ivLength; private IESEngine engine; private int state = -1; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -65,8 +68,14 @@ public class IESCipher public IESCipher(IESEngine engine) { this.engine = engine; + this.ivLength = 0; } + public IESCipher(IESEngine engine, int ivLength) + { + this.engine = engine; + this.ivLength = ivLength; + } public int engineGetBlockSize() { @@ -99,7 +108,6 @@ public class IESCipher return null; } - public AlgorithmParameters engineGetParameters() { if (engineParam == null && engineSpec != null) @@ -259,6 +267,20 @@ public class IESCipher throw new InvalidAlgorithmParameterException("must be passed IES parameters"); } + byte[] nonce = this.engineSpec.getNonce(); + + if (nonce != null) + { + if (ivLength == 0) + { + throw new InvalidAlgorithmParameterException("NONCE present in IES Parameters when none required"); + } + else if (nonce.length != ivLength) + { + throw new InvalidAlgorithmParameterException("NONCE in IES Parameters needs to be " + ivLength + " bytes long"); + } + } + // Parse the recipient's key if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) { @@ -368,11 +390,16 @@ public class IESCipher buffer.reset(); // Convert parameters for use in IESEngine - IESParameters params = new IESWithCipherParameters(engineSpec.getDerivationV(), + CipherParameters params = new IESWithCipherParameters(engineSpec.getDerivationV(), engineSpec.getEncodingV(), engineSpec.getMacKeySize(), engineSpec.getCipherKeySize()); + if (engineSpec.getNonce() != null) + { + params = new ParametersWithIV(params, engineSpec.getNonce()); + } + final ECDomainParameters ecParams = ((ECKeyParameters)key).getParameters(); final byte[] V; @@ -498,4 +525,28 @@ public class IESCipher new PaddedBufferedBlockCipher(new AESEngine()))); } } + + static public class ECIESwithDESedeCBC + extends IESCipher + { + public ECIESwithDESedeCBC() + { + super(new IESEngine(new ECDHBasicAgreement(), + new KDF2BytesGenerator(new SHA1Digest()), + new HMac(new SHA1Digest()), + new PaddedBufferedBlockCipher(new CBCBlockCipher(new DESedeEngine()))), 8); + } + } + + static public class ECIESwithAESCBC + extends IESCipher + { + public ECIESwithAESCBC() + { + super(new IESEngine(new ECDHBasicAgreement(), + new KDF2BytesGenerator(new SHA1Digest()), + new HMac(new SHA1Digest()), + new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()))), 16); + } + } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index 5ddee864c..590cd1550 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -17,6 +17,7 @@ import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x9.X9IntegerConverter; import org.spongycastle.crypto.BasicAgreement; @@ -28,6 +29,7 @@ import org.spongycastle.crypto.agreement.ECMQVBasicAgreement; import org.spongycastle.crypto.agreement.kdf.DHKDFParameters; import org.spongycastle.crypto.agreement.kdf.ECDHKEKGenerator; import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.crypto.params.DESParameters; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; @@ -39,6 +41,7 @@ import org.spongycastle.jce.interfaces.ECPublicKey; import org.spongycastle.jce.interfaces.MQVPrivateKey; import org.spongycastle.jce.interfaces.MQVPublicKey; import org.spongycastle.util.Integers; +import org.spongycastle.util.Strings; /** * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 @@ -51,9 +54,12 @@ public class KeyAgreementSpi { private static final X9IntegerConverter converter = new X9IntegerConverter(); private static final Hashtable algorithms = new Hashtable(); + private static final Hashtable oids = new Hashtable(); + private static final Hashtable des = new Hashtable(); static { + Integer i64 = Integers.valueOf(64); Integer i128 = Integers.valueOf(128); Integer i192 = Integers.valueOf(192); Integer i256 = Integers.valueOf(256); @@ -65,6 +71,18 @@ public class KeyAgreementSpi algorithms.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192); algorithms.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256); algorithms.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192); + algorithms.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192); + algorithms.put(OIWObjectIdentifiers.desCBC.getId(), i64); + + oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + oids.put("DES", OIWObjectIdentifiers.desCBC); + + des.put("DES", "DES"); + des.put("DESEDE", "DES"); + des.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES"); } private String kaAlgorithm; @@ -76,7 +94,7 @@ public class KeyAgreementSpi private byte[] bigIntToBytes( BigInteger r) { - return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getAffineXCoord())); + return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve())); } protected KeyAgreementSpi( @@ -175,17 +193,24 @@ public class KeyAgreementSpi throws NoSuchAlgorithmException { byte[] secret = bigIntToBytes(result); + String algKey = Strings.toUpperCase(algorithm); + String oidAlgorithm = algorithm; + + if (oids.containsKey(algKey)) + { + oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId(); + } if (kdf != null) { - if (!algorithms.containsKey(algorithm)) + if (!algorithms.containsKey(oidAlgorithm)) { throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); } - int keySize = ((Integer)algorithms.get(algorithm)).intValue(); + int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue(); - DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret); + DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret); byte[] keyBytes = new byte[keySize / 8]; kdf.init(params); @@ -194,7 +219,21 @@ public class KeyAgreementSpi } else { - // TODO Should we be ensuring the key is the right length? + if (algorithms.containsKey(oidAlgorithm)) + { + Integer length = (Integer)algorithms.get(oidAlgorithm); + + byte[] key = new byte[length.intValue() / 8]; + + System.arraycopy(secret, 0, key, 0, key.length); + + secret = key; + } + } + + if (des.containsKey(oidAlgorithm)) + { + DESParameters.setOddParity(secret); } return new SecretKeySpec(secret, algorithm); @@ -206,6 +245,11 @@ public class KeyAgreementSpi SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + if (params != null) + { + throw new InvalidAlgorithmParameterException("No algorithm parameters supported"); + } + initFromKey(key); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java index dec8acd9a..bd24d1aad 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java @@ -85,23 +85,21 @@ public abstract class KeyPairGeneratorSpi { this.strength = strength; this.random = random; - ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength)); - if (ecParams != null) - { - try - { - initialize(ecParams, random); - } - catch (InvalidAlgorithmParameterException e) - { - throw new InvalidParameterException("key size not configurable."); - } - } - else + ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength)); + if (ecParams == null) { throw new InvalidParameterException("unknown key size."); } + + try + { + initialize(ecParams, random); + } + catch (InvalidAlgorithmParameterException e) + { + throw new InvalidParameterException("key size not configurable."); + } } public void initialize( @@ -109,97 +107,42 @@ public abstract class KeyPairGeneratorSpi SecureRandom random) throws InvalidAlgorithmParameterException { - if (params instanceof ECParameterSpec) + if (params == null) + { + ECParameterSpec implicitCA = configuration.getEcImplicitlyCa(); + if (implicitCA == null) + { + throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); + } + + this.ecParams = null; + this.param = createKeyGenParamsBC(implicitCA, random); + } + else if (params instanceof ECParameterSpec) { - ECParameterSpec p = (ECParameterSpec)params; this.ecParams = params; - - param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); - - engine.init(param); - initialised = true; + this.param = createKeyGenParamsBC((ECParameterSpec)params, random); } else if (params instanceof java.security.spec.ECParameterSpec) { - java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params; this.ecParams = params; - - ECCurve curve = EC5Util.convertCurve(p.getCurve()); - ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); - - param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); - - engine.init(param); - initialised = true; + this.param = createKeyGenParamsJCE((java.security.spec.ECParameterSpec)params, random); } - else if (params instanceof ECGenParameterSpec || params instanceof ECNamedCurveGenParameterSpec) + else if (params instanceof ECGenParameterSpec) { - String curveName; - - if (params instanceof ECGenParameterSpec) - { - curveName = ((ECGenParameterSpec)params).getName(); - } - else - { - curveName = ((ECNamedCurveGenParameterSpec)params).getName(); - } - - X9ECParameters ecP = ECNamedCurveTable.getByName(curveName); - if (ecP == null) - { - // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) - try - { - ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName); - ecP = ECNamedCurveTable.getByOID(oid); - if (ecP == null) - { - throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); - } - } - catch (IllegalArgumentException ex) - { - throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); - } - } - - this.ecParams = new ECNamedCurveSpec( - curveName, - ecP.getCurve(), - ecP.getG(), - ecP.getN(), - ecP.getH(), - null); // ecP.getSeed()); Work-around JDK bug -- it won't look up named curves properly if seed is present - - java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams; - - ECCurve curve = EC5Util.convertCurve(p.getCurve()); - ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); - - param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random); - - engine.init(param); - initialised = true; + initializeNamedCurve(((ECGenParameterSpec)params).getName(), random); } - else if (params == null && configuration.getEcImplicitlyCa() != null) + else if (params instanceof ECNamedCurveGenParameterSpec) { - ECParameterSpec p = configuration.getEcImplicitlyCa(); - this.ecParams = params; - - param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); - - engine.init(param); - initialised = true; - } - else if (params == null && configuration.getEcImplicitlyCa() == null) - { - throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); + initializeNamedCurve(((ECNamedCurveGenParameterSpec)params).getName(), random); } else { throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); } + + engine.init(param); + initialised = true; } public KeyPair generateKeyPair() @@ -235,6 +178,58 @@ public abstract class KeyPairGeneratorSpi return new KeyPair(pubKey, new BCECPrivateKey(algorithm, priv, pubKey, p, configuration)); } } + + protected ECKeyGenerationParameters createKeyGenParamsBC(ECParameterSpec p, SecureRandom r) + { + return new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), r); + } + + protected ECKeyGenerationParameters createKeyGenParamsJCE(java.security.spec.ECParameterSpec p, SecureRandom r) + { + ECCurve curve = EC5Util.convertCurve(p.getCurve()); + ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false); + BigInteger n = p.getOrder(); + BigInteger h = BigInteger.valueOf(p.getCofactor()); + ECDomainParameters dp = new ECDomainParameters(curve, g, n, h); + return new ECKeyGenerationParameters(dp, r); + } + + protected ECNamedCurveSpec createNamedCurveSpec(String curveName) + throws InvalidAlgorithmParameterException + { + // NOTE: Don't bother with custom curves here as the curve will be converted to JCE type shortly + + X9ECParameters p = ECNamedCurveTable.getByName(curveName); + if (p == null) + { + try + { + // Check whether it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) + p = ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(curveName)); + if (p == null) + { + throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); + } + } + catch (IllegalArgumentException ex) + { + throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); + } + } + + // Work-around for JDK bug -- it won't look up named curves properly if seed is present + byte[] seed = null; //p.getSeed(); + + return new ECNamedCurveSpec(curveName, p.getCurve(), p.getG(), p.getN(), p.getH(), seed); + } + + protected void initializeNamedCurve(String curveName, SecureRandom random) + throws InvalidAlgorithmParameterException + { + ECNamedCurveSpec namedCurve = createNamedCurveSpec(curveName); + this.ecParams = namedCurve; + this.param = createKeyGenParamsJCE(namedCurve, random); + } } public static class ECDSA diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java index 9f1a766e9..5846e3930 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java @@ -223,7 +223,7 @@ public class SignatureSpi { public ecCVCDSA() { - super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder()); + super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder()); } } @@ -232,7 +232,7 @@ public class SignatureSpi { public ecCVCDSA224() { - super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder()); + super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder()); } } @@ -241,7 +241,7 @@ public class SignatureSpi { public ecCVCDSA256() { - super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder()); + super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder()); } } @@ -250,7 +250,7 @@ public class SignatureSpi { public ecCVCDSA384() { - super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder()); + super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder()); } } @@ -259,7 +259,16 @@ public class SignatureSpi { public ecCVCDSA512() { - super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder()); + super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder()); + } + } + + static public class ecPlainDSARP160 + extends SignatureSpi + { + public ecPlainDSARP160() + { + super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder()); } } @@ -293,7 +302,7 @@ public class SignatureSpi } } - private static class CVCDSAEncoder + private static class PlainDSAEncoder implements DSAEncoder { public byte[] encode( diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java index 4e2297932..ca441966e 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java @@ -13,14 +13,13 @@ import java.util.Enumeration; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.cryptopro.ECGOST3410NamedCurves; @@ -289,9 +288,9 @@ public class BCECGOST3410PrivateKey } ASN1Encodable privKey = info.parsePrivateKey(); - if (privKey instanceof DERInteger) + if (privKey instanceof ASN1Integer) { - DERInteger derD = DERInteger.getInstance(privKey); + ASN1Integer derD = ASN1Integer.getInstance(privKey); this.d = derD.getValue(); } @@ -351,7 +350,7 @@ public class BCECGOST3410PrivateKey if (ecSpec instanceof ECNamedCurveSpec) { - DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); if (curveOid == null) // guess it's the OID { curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java index c0d10ebb7..9aa744bf5 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java @@ -32,6 +32,8 @@ import org.spongycastle.jce.provider.BouncyCastleProvider; import org.spongycastle.jce.spec.ECNamedCurveParameterSpec; import org.spongycastle.jce.spec.ECNamedCurveSpec; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.custom.sec.SecP256K1Point; +import org.spongycastle.math.ec.custom.sec.SecP256R1Point; public class BCECGOST3410PublicKey implements ECPublicKey, org.spongycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -316,14 +318,7 @@ public class BCECGOST3410PublicKey { if (ecSpec == null) { - if (q instanceof org.spongycastle.math.ec.ECPoint.Fp) - { - return new org.spongycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord()); - } - else - { - return new org.spongycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord()); - } + return q.getDetachedPoint(); } return q; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/AlgorithmParametersSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/AlgorithmParametersSpi.java index 41b9a60fd..5a65c0b24 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/AlgorithmParametersSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/AlgorithmParametersSpi.java @@ -8,7 +8,6 @@ import javax.crypto.spec.DHParameterSpec; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters; import org.spongycastle.jce.spec.ElGamalParameterSpec; @@ -95,7 +94,7 @@ public class AlgorithmParametersSpi { try { - ElGamalParameter elP = new ElGamalParameter((ASN1Sequence)ASN1Primitive.fromByteArray(params)); + ElGamalParameter elP = ElGamalParameter.getInstance(ASN1Primitive.fromByteArray(params)); currentSpec = new ElGamalParameterSpec(elP.getP(), elP.getG()); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPrivateKey.java index 4f02ba3fa..73a965a72 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPrivateKey.java @@ -14,8 +14,6 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; @@ -73,8 +71,8 @@ public class BCElGamalPrivateKey PrivateKeyInfo info) throws IOException { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)info.getAlgorithmId().getParameters()); - DERInteger derX = ASN1Integer.getInstance(info.parsePrivateKey()); + ElGamalParameter params = ElGamalParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters()); + ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey()); this.x = derX.getValue(); this.elSpec = new ElGamalParameterSpec(params.getP(), params.getG()); @@ -112,7 +110,7 @@ public class BCElGamalPrivateKey { try { - PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new DERInteger(getX())); + PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new ASN1Integer(getX())); return info.getEncoded(ASN1Encoding.DER); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPublicKey.java index 20d668cf4..86ee5226c 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/elgamal/BCElGamalPublicKey.java @@ -10,8 +10,7 @@ import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -75,12 +74,12 @@ public class BCElGamalPublicKey BCElGamalPublicKey( SubjectPublicKeyInfo info) { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)info.getAlgorithmId().getParameters()); - DERInteger derY = null; + ElGamalParameter params = ElGamalParameter.getInstance(info.getAlgorithm().getParameters()); + ASN1Integer derY = null; try { - derY = (DERInteger)info.parsePublicKey(); + derY = (ASN1Integer)info.parsePublicKey(); } catch (IOException e) { @@ -105,7 +104,7 @@ public class BCElGamalPublicKey { try { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new DERInteger(y)); + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new ASN1Integer(y)); return info.getEncoded(ASN1Encoding.DER); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ies/AlgorithmParametersSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ies/AlgorithmParametersSpi.java index 1fd8b90d5..f5de87c8a 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ies/AlgorithmParametersSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ies/AlgorithmParametersSpi.java @@ -6,10 +6,10 @@ import java.security.spec.InvalidParameterSpecException; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DERSequence; import org.spongycastle.jce.spec.IESParameterSpec; @@ -48,7 +48,7 @@ public class AlgorithmParametersSpi v.add(new DEROctetString(currentSpec.getDerivationV())); v.add(new DEROctetString(currentSpec.getEncodingV())); - v.add(new DERInteger(currentSpec.getMacKeySize())); + v.add(new ASN1Integer(currentSpec.getMacKeySize())); return new DERSequence(v).getEncoded(ASN1Encoding.DER); } @@ -104,7 +104,7 @@ public class AlgorithmParametersSpi this.currentSpec = new IESParameterSpec( ((ASN1OctetString)s.getObjectAt(0)).getOctets(), ((ASN1OctetString)s.getObjectAt(0)).getOctets(), - ((DERInteger)s.getObjectAt(0)).getValue().intValue()); + ((ASN1Integer)s.getObjectAt(0)).getValue().intValue()); } catch (ClassCastException e) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java index e76e087b3..1e63f3b5c 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPrivateKey.java @@ -55,6 +55,12 @@ public class BCRSAPrivateKey this.privateExponent = key.getPrivateExponent(); } + BCRSAPrivateKey(org.spongycastle.asn1.pkcs.RSAPrivateKey key) + { + this.modulus = key.getModulus(); + this.privateExponent = key.getPrivateExponent(); + } + public BigInteger getModulus() { return modulus; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java index bff5aac65..7a4454c53 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/BCRSAPublicKey.java @@ -1,5 +1,6 @@ package org.spongycastle.jcajce.provider.asymmetric.rsa; +import java.io.EOFException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -156,6 +157,10 @@ public class BCRSAPublicKey { algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER; } + catch (EOFException e) + { + algorithmIdentifier = DEFAULT_ALGORITHM_IDENTIFIER; + } } private void writeObject( diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java index 6e1a928d0..6edd4aef8 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java @@ -307,7 +307,7 @@ public class CipherSpi } else { - throw new IllegalArgumentException("unknown parameter type."); + throw new InvalidAlgorithmParameterException("unknown parameter type: " + params.getClass().getName()); } if (!(cipher instanceof RSABlindedEngine)) diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java index 2b18b93b3..fcc973af5 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/rsa/KeyFactorySpi.java @@ -137,7 +137,16 @@ public class KeyFactorySpi if (RSAUtil.isRsaOid(algOid)) { - return new BCRSAPrivateCrtKey(keyInfo); + RSAPrivateKey rsaPrivKey = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey()); + + if (rsaPrivKey.getCoefficient().intValue() == 0) + { + return new BCRSAPrivateKey(rsaPrivKey); + } + else + { + return new BCRSAPrivateCrtKey(keyInfo); + } } else { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java index 13231c51c..5ced82ec7 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java @@ -1,6 +1,5 @@ package org.spongycastle.jcajce.provider.asymmetric.util; -import java.io.IOException; import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/EC5Util.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/EC5Util.java index b6fc1ee35..d1f49a80f 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/EC5Util.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/EC5Util.java @@ -7,22 +7,46 @@ import java.security.spec.ECFieldFp; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import org.spongycastle.asn1.x9.ECNamedCurveTable; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.crypto.ec.CustomNamedCurves; import org.spongycastle.jce.spec.ECNamedCurveParameterSpec; import org.spongycastle.jce.spec.ECNamedCurveSpec; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; public class EC5Util { + private static Map customCurves = new HashMap(); + + static + { + Enumeration e = CustomNamedCurves.getNames(); + while (e.hasMoreElements()) + { + String name = (String)e.nextElement(); + + X9ECParameters curveParams = ECNamedCurveTable.getByName(name); + if (curveParams != null) // there may not be a regular curve, may just be a custom curve. + { + customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve()); + } + } + } + public static EllipticCurve convertCurve( ECCurve curve, byte[] seed) { // TODO: the Sun EC implementation doesn't currently handle the seed properly // so at the moment it's set to null. Should probably look at making this configurable - if (curve instanceof ECCurve.Fp) + if (ECAlgorithms.isFpCurve(curve)) { - return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); + return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), null); } else { @@ -53,7 +77,14 @@ public class EC5Util if (field instanceof ECFieldFp) { - return new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + ECCurve.Fp curve = new ECCurve.Fp(((ECFieldFp)field).getP(), a, b); + + if (customCurves.containsKey(curve)) + { + return (ECCurve)customCurves.get(curve); + } + + return curve; } else { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/ECUtil.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/ECUtil.java index b84c7ad55..c3251a8d6 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/ECUtil.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/ECUtil.java @@ -13,6 +13,7 @@ import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x9.X962NamedCurves; import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.crypto.ec.CustomNamedCurves; import org.spongycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; @@ -241,11 +242,15 @@ public class ECUtil public static X9ECParameters getNamedCurveByOid( ASN1ObjectIdentifier oid) { - X9ECParameters params = X962NamedCurves.getByOID(oid); - + X9ECParameters params = CustomNamedCurves.getByOID(oid); + if (params == null) { - params = SECNamedCurves.getByOID(oid); + params = X962NamedCurves.getByOID(oid); + if (params == null) + { + params = SECNamedCurves.getByOID(oid); + } if (params == null) { params = NISTNamedCurves.getByOID(oid); diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java index b46e1cf4c..5ae93fdb3 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/util/PKCS12BagAttributeCarrierImpl.java @@ -12,7 +12,6 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; public class PKCS12BagAttributeCarrierImpl @@ -90,7 +89,7 @@ public class PKCS12BagAttributeCarrierImpl while (e.hasMoreElements()) { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); aOut.writeObject(oid); aOut.writeObject((ASN1Encodable)pkcs12Attributes.get(oid)); diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/PEMUtil.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/PEMUtil.java index acc6d0356..4eb704d9a 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/PEMUtil.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/PEMUtil.java @@ -33,11 +33,6 @@ public class PEMUtil { while (((c = in.read()) != '\r') && c != '\n' && (c >= 0)) { - if (c == '\r') - { - continue; - } - l.append((char)c); } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java index 41824a085..6c988b8d9 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java @@ -11,9 +11,9 @@ import java.security.spec.PSSParameterSpec; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Null; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -76,7 +76,7 @@ class X509SignatureUtil { ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params); - return getDigestAlgName((DERObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA"; + return getDigestAlgName((ASN1ObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA"; } } @@ -88,7 +88,7 @@ class X509SignatureUtil * representations rather the the algorithm identifier (if possible). */ private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/config/ConfigurableProvider.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/config/ConfigurableProvider.java index fa93489f7..a9679dc33 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/config/ConfigurableProvider.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/config/ConfigurableProvider.java @@ -15,7 +15,7 @@ public interface ConfigurableProvider static final String THREAD_LOCAL_EC_IMPLICITLY_CA = "threadLocalEcImplicitlyCa"; /** - * Elliptic Curve CA parameters - thread local version + * Elliptic Curve CA parameters - VM wide version */ static final String EC_IMPLICITLY_CA = "ecImplicitlyCa"; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index 115a00012..c8891aa7a 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -84,6 +84,8 @@ import org.spongycastle.asn1.x509.Extension; import org.spongycastle.asn1.x509.SubjectKeyIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x509.X509ObjectIdentifiers; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.SHA1Digest; import org.spongycastle.jcajce.provider.config.PKCS12StoreParameter; import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.spongycastle.jcajce.spec.GOST28147ParameterSpec; @@ -209,7 +211,7 @@ public class PKCS12KeyStoreSpi SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( (ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded())); - return new SubjectKeyIdentifier(info); + return new SubjectKeyIdentifier(getDigest(info)); } catch (Exception e) { @@ -217,6 +219,17 @@ public class PKCS12KeyStoreSpi } } + private static byte[] getDigest(SubjectPublicKeyInfo spki) + { + Digest digest = new SHA1Digest(); + byte[] resBuf = new byte[digest.getDigestSize()]; + + byte[] bytes = spki.getPublicKeyData().getBytes(); + digest.update(bytes, 0, bytes.length); + digest.doFinal(resBuf, 0); + return resBuf; + } + public void setRandom( SecureRandom rand) { @@ -663,6 +676,7 @@ public class PKCS12KeyStoreSpi throws IOException { ASN1ObjectIdentifier algorithm = algId.getAlgorithm(); + int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; if (algorithm.on(PKCSObjectIdentifiers.pkcs_12PbeIds)) { @@ -680,7 +694,7 @@ public class PKCS12KeyStoreSpi key.setTryWrongPKCS12Zero(wrongPKCS12Zero); Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider); - int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; + cipher.init(mode, key, defParams); return cipher.doFinal(data); } @@ -693,7 +707,7 @@ public class PKCS12KeyStoreSpi { try { - Cipher cipher = createCipher(Cipher.DECRYPT_MODE, password, algId); + Cipher cipher = createCipher(mode, password, algId); return cipher.doFinal(data); } @@ -1021,9 +1035,9 @@ public class PKCS12KeyStoreSpi Enumeration e = b.getBagAttributes().getObjects(); while (e.hasMoreElements()) { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); + ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement()); + ASN1ObjectIdentifier aOid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0)); + ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1)); ASN1Primitive attr = null; if (attrSet.size() > 0) @@ -1044,16 +1058,16 @@ public class PKCS12KeyStoreSpi { bagAttr.setBagAttribute(aOid, attr); } - } - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; + if (aOid.equals(pkcs_9_at_friendlyName)) + { + alias = ((DERBMPString)attr).getString(); + keys.put(alias, privKey); + } + else if (aOid.equals(pkcs_9_at_localKeyId)) + { + localId = (ASN1OctetString)attr; + } } } @@ -1121,38 +1135,43 @@ public class PKCS12KeyStoreSpi Enumeration e = b.getBagAttributes().getObjects(); while (e.hasMoreElements()) { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Primitive attr = (ASN1Primitive)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0); - PKCS12BagAttributeCarrier bagAttr = null; + ASN1Sequence sq = ASN1Sequence.getInstance(e.nextElement()); + ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(sq.getObjectAt(0)); + ASN1Set attrSet = ASN1Set.getInstance(sq.getObjectAt(1)); - if (cert instanceof PKCS12BagAttributeCarrier) + if (attrSet.size() > 0) // sometimes this is empty! { - bagAttr = (PKCS12BagAttributeCarrier)cert; + ASN1Primitive attr = (ASN1Primitive)attrSet.getObjectAt(0); + PKCS12BagAttributeCarrier bagAttr = null; - ASN1Encodable existing = bagAttr.getBagAttribute(oid); - if (existing != null) + if (cert instanceof PKCS12BagAttributeCarrier) { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) + bagAttr = (PKCS12BagAttributeCarrier)cert; + + ASN1Encodable existing = bagAttr.getBagAttribute(oid); + if (existing != null) { - throw new IOException( - "attempt to add existing attribute with different value"); + // OK, but the value has to be the same + if (!existing.toASN1Primitive().equals(attr)) + { + throw new IOException( + "attempt to add existing attribute with different value"); + } + } + else + { + bagAttr.setBagAttribute(oid, attr); } } - else - { - bagAttr.setBagAttribute(oid, attr); - } - } - if (oid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - } - else if (oid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; + if (oid.equals(pkcs_9_at_friendlyName)) + { + alias = ((DERBMPString)attr).getString(); + } + else if (oid.equals(pkcs_9_at_localKeyId)) + { + localId = (ASN1OctetString)attr; + } } } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/AES.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/AES.java index 21a14482e..2ad0d2d43 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/AES.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/AES.java @@ -20,6 +20,7 @@ import org.spongycastle.crypto.CipherKeyGenerator; import org.spongycastle.crypto.engines.AESFastEngine; import org.spongycastle.crypto.engines.AESWrapEngine; import org.spongycastle.crypto.engines.RFC3211WrapEngine; +import org.spongycastle.crypto.engines.RFC5649WrapEngine; import org.spongycastle.crypto.generators.Poly1305KeyGenerator; import org.spongycastle.crypto.macs.CMac; import org.spongycastle.crypto.macs.GMac; @@ -153,7 +154,15 @@ public final class AES } } - + public static class RFC5649Wrap + extends BaseWrapCipher + { + public RFC5649Wrap() + { + super(new RFC5649WrapEngine(new AESFastEngine())); + } + } + /** * PBEWithAES-CBC */ @@ -433,9 +442,9 @@ public final class AES { try { - Constructor constructor = gcmSpecClass.getConstructor(new Class[] { byte[].class, Integer.class }); + Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class }); - return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { gcmParams.getNonce(), Integers.valueOf(gcmParams.getIcvLen()) }); + return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen()), gcmParams.getNonce() }); } catch (NoSuchMethodException e) { @@ -512,7 +521,9 @@ public final class AES provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP"); provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP"); provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_wrap, "AESWRAP"); + provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap"); + provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap"); provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM"); provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "GCM"); diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/GOST28147.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/GOST28147.java index 8b4404298..c12ba7cd7 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/GOST28147.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/GOST28147.java @@ -90,7 +90,7 @@ public final class GOST28147 SecureRandom random) throws InvalidAlgorithmParameterException { - throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation."); + throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for GOST28147 parameter generation."); } protected AlgorithmParameters engineGenerateParameters() diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/SipHash.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/SipHash.java index 82d7e85eb..b568046a1 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/SipHash.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/SipHash.java @@ -1,6 +1,8 @@ package org.spongycastle.jcajce.provider.symmetric; +import org.spongycastle.crypto.CipherKeyGenerator; import org.spongycastle.jcajce.provider.config.ConfigurableProvider; +import org.spongycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; import org.spongycastle.jcajce.provider.symmetric.util.BaseMac; import org.spongycastle.jcajce.provider.util.AlgorithmProvider; @@ -9,11 +11,11 @@ public final class SipHash private SipHash() { } - - public static class Mac + + public static class Mac24 extends BaseMac { - public Mac() + public Mac24() { super(new org.spongycastle.crypto.macs.SipHash()); } @@ -28,6 +30,15 @@ public final class SipHash } } + public static class KeyGen + extends BaseKeyGenerator + { + public KeyGen() + { + super("SipHash", 128, new CipherKeyGenerator()); + } + } + public static class Mappings extends AlgorithmProvider { @@ -39,9 +50,13 @@ public final class SipHash public void configure(ConfigurableProvider provider) { - provider.addAlgorithm("Mac.SIPHASH", PREFIX + "$Mac"); - provider.addAlgorithm("Alg.Alias.Mac.SIPHASH-2-4", "SIPHASH"); + provider.addAlgorithm("Mac.SIPHASH-2-4", PREFIX + "$Mac24"); + provider.addAlgorithm("Alg.Alias.Mac.SIPHASH", "SIPHASH-2-4"); provider.addAlgorithm("Mac.SIPHASH-4-8", PREFIX + "$Mac48"); + + provider.addAlgorithm("KeyGenerator.SIPHASH", PREFIX + "$KeyGen"); + provider.addAlgorithm("Alg.Alias.KeyGenerator.SIPHASH-2-4", "SIPHASH"); + provider.addAlgorithm("Alg.Alias.KeyGenerator.SIPHASH-4-8", "SIPHASH"); } } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java index 9a3bf722a..8d7bb13c2 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java @@ -1,5 +1,6 @@ package org.spongycastle.jcajce.provider.symmetric.util; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.security.AlgorithmParameters; @@ -162,6 +163,11 @@ public class BaseBlockCipher protected byte[] engineGetIV() { + if (aeadParams != null) + { + return aeadParams.getNonce(); + } + return (ivParam != null) ? ivParam.getIV() : null; } @@ -334,7 +340,9 @@ public class BaseBlockCipher { if (engineProvider != null) { - // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03 + /* + * RFC 7253 4.2. Nonce is a string of no more than 120 bits + */ ivLength = 15; cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get())); } @@ -814,10 +822,6 @@ public class BaseBlockCipher { throw new IllegalBlockSizeException(e.getMessage()); } - catch (InvalidCipherTextException e) - { - throw new BadPaddingException(e.getMessage()); - } if (len == tmp.length) { @@ -858,10 +862,6 @@ public class BaseBlockCipher { throw new IllegalBlockSizeException(e.getMessage()); } - catch (InvalidCipherTextException e) - { - throw new BadPaddingException(e.getMessage()); - } } private boolean isAEADModeName( @@ -898,7 +898,8 @@ public class BaseBlockCipher throws DataLengthException; public int doFinal(byte[] out, int outOff) - throws IllegalStateException, InvalidCipherTextException; + throws IllegalStateException, + BadPaddingException; } private static class BufferedGenericBlockCipher @@ -967,15 +968,48 @@ public class BaseBlockCipher return cipher.processBytes(in, inOff, len, out, outOff); } - public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException + public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException { - return cipher.doFinal(out, outOff); + try + { + return cipher.doFinal(out, outOff); + } + catch (InvalidCipherTextException e) + { + throw new BadPaddingException(e.getMessage()); + } } } private static class AEADGenericBlockCipher implements GenericBlockCipher { + private static final Constructor aeadBadTagConstructor; + + static { + Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException"); + if (aeadBadTagClass != null) + { + aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass); + } + else + { + aeadBadTagConstructor = null; + } + } + + private static Constructor findExceptionConstructor(Class clazz) + { + try + { + return clazz.getConstructor(new Class[]{String.class}); + } + catch (Exception e) + { + return null; + } + } + private AEADBlockCipher cipher; AEADGenericBlockCipher(AEADBlockCipher cipher) @@ -1029,9 +1063,33 @@ public class BaseBlockCipher return cipher.processBytes(in, inOff, len, out, outOff); } - public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException + public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException { - return cipher.doFinal(out, outOff); + try + { + return cipher.doFinal(out, outOff); + } + catch (InvalidCipherTextException e) + { + if (aeadBadTagConstructor != null) + { + BadPaddingException aeadBadTag = null; + try + { + aeadBadTag = (BadPaddingException)aeadBadTagConstructor + .newInstance(new Object[]{e.getMessage()}); + } + catch (Exception i) + { + // Shouldn't happen, but fall through to BadPaddingException + } + if (aeadBadTag != null) + { + throw aeadBadTag; + } + } + throw new BadPaddingException(e.getMessage()); + } } } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java index 92027555c..e362f3830 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java @@ -17,10 +17,8 @@ import javax.crypto.spec.PBEParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.RC5ParameterSpec; -import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; -import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; @@ -57,15 +55,6 @@ public class BaseStreamCipher this.ivLength = ivLength; } - protected BaseStreamCipher( - BlockCipher engine, - int ivLength) - { - this.ivLength = ivLength; - - cipher = new StreamBlockCipher(engine); - } - protected int engineGetBlockSize() { return 0; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java index 39f4bb027..ce1909c02 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java @@ -32,6 +32,7 @@ import org.spongycastle.crypto.InvalidCipherTextException; import org.spongycastle.crypto.Wrapper; import org.spongycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.crypto.params.ParametersWithRandom; import org.spongycastle.jce.provider.BouncyCastleProvider; public abstract class BaseWrapCipher @@ -164,6 +165,11 @@ public abstract class BaseWrapCipher param = new ParametersWithIV(param, iv); } + if (random != null) + { + param = new ParametersWithRandom(param, random); + } + switch (opmode) { case Cipher.WRAP_MODE: diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/PBKDF2KeySpec.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/PBKDF2KeySpec.java index 68629058b..7bfe09af2 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/PBKDF2KeySpec.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/PBKDF2KeySpec.java @@ -4,11 +4,23 @@ import javax.crypto.spec.PBEKeySpec; import org.spongycastle.asn1.x509.AlgorithmIdentifier; +/** + * Extension of PBEKeySpec which takes into account the PRF algorithm setting available in PKCS#5 PBKDF2. + */ public class PBKDF2KeySpec extends PBEKeySpec { private AlgorithmIdentifier prf; + /** + * Base constructor. + * + * @param password password to use as the seed of the PBE key generator. + * @param salt salt to use in the generator, + * @param iterationCount iteration count to use in the generator. + * @param keySize size of the key to be generated. + * @param prf identifier and parameters for the PRF algorithm to use. + */ public PBKDF2KeySpec(char[] password, byte[] salt, int iterationCount, int keySize, AlgorithmIdentifier prf) { super(password, salt, iterationCount, keySize); diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/SkeinParameterSpec.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/SkeinParameterSpec.java index ee3bb4346..e92fde230 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/SkeinParameterSpec.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/spec/SkeinParameterSpec.java @@ -10,6 +10,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.Locale; import java.util.Map; import org.spongycastle.util.Arrays; @@ -247,6 +248,41 @@ public class SkeinParameterSpec } } + /** + * Implements the recommended personalisation format for Skein defined in Section 4.11 of + * the Skein 1.3 specification. You may need to use this method if the default locale + * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible implementations. + *+ * The format is
YYYYMMDD email@address distinguisher
, encoded to a byte + * sequence using UTF-8 encoding. + * + * @param date the date the personalised application of the Skein was defined. + * @param dateLocale locale to be used for date interpretation. + * @param emailAddress the email address of the creation of the personalised application. + * @param distinguisher an arbitrary personalisation string distinguishing the application. + * @return the current builder. + */ + public Builder setPersonalisation(Date date, Locale dateLocale, String emailAddress, String distinguisher) + { + try + { + final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8"); + final DateFormat format = new SimpleDateFormat("YYYYMMDD", dateLocale); + out.write(format.format(date)); + out.write(" "); + out.write(emailAddress); + out.write(" "); + out.write(distinguisher); + out.close(); + return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray()); + } + catch (IOException e) + { + throw new IllegalStateException("Byte I/O failed: " + e); + } + } + /** * Sets the {@link org.spongycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY_IDENTIFIER} parameter. */ diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/DefaultJcaJceHelper.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/DefaultJcaJceHelper.java similarity index 93% rename from extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/DefaultJcaJceHelper.java rename to extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/DefaultJcaJceHelper.java index ada25f694..0a805fdcb 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/DefaultJcaJceHelper.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/DefaultJcaJceHelper.java @@ -1,4 +1,4 @@ -package org.spongycastle.jcajce; +package org.spongycastle.jcajce.util; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; @@ -17,6 +17,10 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms using the default JCA/JCE mechanism (i.e. + * without specifying a provider). + */ public class DefaultJcaJceHelper implements JcaJceHelper { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceHelper.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceHelper.java similarity index 95% rename from extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceHelper.java rename to extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceHelper.java index 88f129be0..f15cdefed 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/JcaJceHelper.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceHelper.java @@ -1,4 +1,4 @@ -package org.spongycastle.jcajce; +package org.spongycastle.jcajce.util; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; @@ -18,6 +18,9 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * Factory interface for instantiating JCA/JCE primitives. + */ public interface JcaJceHelper { Cipher createCipher( diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceUtils.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceUtils.java new file mode 100644 index 000000000..b1bf5feca --- /dev/null +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/JcaJceUtils.java @@ -0,0 +1,124 @@ +package org.spongycastle.jcajce.util; + +import java.io.IOException; +import java.security.AlgorithmParameters; + +import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; + +/** + * General JCA/JCE utility methods. + */ +public class JcaJceUtils +{ + private JcaJceUtils() + { + + } + + /** + * Extract an ASN.1 encodable from an AlgorithmParameters object. + * + * @param params the object to get the encoding used to create the return value. + * @return an ASN.1 object representing the primitives making up the params parameter. + * @throws IOException if an encoding cannot be extracted. + */ + public static ASN1Encodable extractParameters(AlgorithmParameters params) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + ASN1Encodable asn1Params; + try + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1")); + } + catch (Exception ex) + { + asn1Params = ASN1Primitive.fromByteArray(params.getEncoded()); + } + + return asn1Params; + } + + /** + * Load an AlgorithmParameters object with the passed in ASN.1 encodable - if possible. + * + * @param params the AlgorithmParameters object to be initialised. + * @param sParams the ASN.1 encodable to initialise params with. + * @throws IOException if the parameters cannot be initialised. + */ + public static void loadParameters(AlgorithmParameters params, ASN1Encodable sParams) + throws IOException + { + // we try ASN.1 explicitly first just in case and then role back to the default. + try + { + params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1"); + } + catch (Exception ex) + { + params.init(sParams.toASN1Primitive().getEncoded()); + } + } + + /** + * Attempt to find a standard JCA name for the digest represented by the past in OID. + * + * @param digestAlgOID the OID of the digest algorithm of interest. + * @return a string representing the standard name - the OID as a string if none available. + */ + public static String getDigestAlgName( + ASN1ObjectIdentifier digestAlgOID) + { + if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) + { + return "MD5"; + } + else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID)) + { + return "SHA1"; + } + else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID)) + { + return "SHA224"; + } + else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID)) + { + return "SHA256"; + } + else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID)) + { + return "SHA384"; + } + else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID)) + { + return "SHA512"; + } + else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID)) + { + return "RIPEMD128"; + } + else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID)) + { + return "RIPEMD160"; + } + else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID)) + { + return "RIPEMD256"; + } + else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID)) + { + return "GOST3411"; + } + else + { + return digestAlgOID.getId(); + } + } +} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/NamedJcaJceHelper.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/NamedJcaJceHelper.java similarity index 96% rename from extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/NamedJcaJceHelper.java rename to extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/NamedJcaJceHelper.java index 117ca4ec1..fde273160 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/NamedJcaJceHelper.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/NamedJcaJceHelper.java @@ -1,4 +1,4 @@ -package org.spongycastle.jcajce; +package org.spongycastle.jcajce.util; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; @@ -18,6 +18,9 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms using a specific named provider. + */ public class NamedJcaJceHelper implements JcaJceHelper { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/ProviderJcaJceHelper.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java similarity index 95% rename from extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/ProviderJcaJceHelper.java rename to extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java index e4cca6f78..2a85a7375 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/ProviderJcaJceHelper.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java @@ -1,4 +1,4 @@ -package org.spongycastle.jcajce; +package org.spongycastle.jcajce.util; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; @@ -18,6 +18,9 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +/** + * {@link JcaJceHelper} that obtains all algorithms from a specific {@link Provider} instance. + */ public class ProviderJcaJceHelper implements JcaJceHelper { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/ECNamedCurveTable.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/ECNamedCurveTable.java index 1a1f1b8a5..e3ebccff7 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/ECNamedCurveTable.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/ECNamedCurveTable.java @@ -21,19 +21,35 @@ public class ECNamedCurveTable public static ECNamedCurveParameterSpec getParameterSpec( String name) { - X9ECParameters ecP = org.spongycastle.asn1.x9.ECNamedCurveTable.getByName(name); + X9ECParameters ecP = org.spongycastle.crypto.ec.CustomNamedCurves.getByName(name); if (ecP == null) { try { - ecP = org.spongycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name)); + ecP = org.spongycastle.crypto.ec.CustomNamedCurves.getByOID(new ASN1ObjectIdentifier(name)); } catch (IllegalArgumentException e) { // ignore - not an oid } + + if (ecP == null) + { + ecP = org.spongycastle.asn1.x9.ECNamedCurveTable.getByName(name); + if (ecP == null) + { + try + { + ecP = org.spongycastle.asn1.x9.ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(name)); + } + catch (IllegalArgumentException e) + { + // ignore - not an oid + } + } + } } - + if (ecP == null) { return null; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS10CertificationRequest.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS10CertificationRequest.java index 74c1ba169..dbc34a54f 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS10CertificationRequest.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS10CertificationRequest.java @@ -24,12 +24,12 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -81,13 +81,13 @@ public class PKCS10CertificationRequest static { - algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); - algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD5WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("MD5WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("RSAWITHMD5", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("SHA1WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("SHA1WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); @@ -101,15 +101,15 @@ public class PKCS10CertificationRequest algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); - algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("RSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); - algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("SHA1WITHDSA", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("DSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384); @@ -129,7 +129,7 @@ public class PKCS10CertificationRequest // // reverse mappings // - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA"); oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA"); oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA"); @@ -137,9 +137,9 @@ public class PKCS10CertificationRequest oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410"); - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); - oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA"); @@ -306,13 +306,13 @@ public class PKCS10CertificationRequest InvalidKeyException, SignatureException { String algorithmName = Strings.toUpperCase(signatureAlgorithm); - DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(algorithmName); + ASN1ObjectIdentifier sigOID = (ASN1ObjectIdentifier)algorithms.get(algorithmName); if (sigOID == null) { try { - sigOID = new DERObjectIdentifier(algorithmName); + sigOID = new ASN1ObjectIdentifier(algorithmName); } catch (Exception e) { @@ -590,7 +590,7 @@ public class PKCS10CertificationRequest } private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS12Util.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS12Util.java index ac0175654..1cf7823a3 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS12Util.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/PKCS12Util.java @@ -10,10 +10,10 @@ import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.pkcs.ContentInfo; @@ -104,7 +104,7 @@ public class PKCS12Util } private static byte[] calculatePbeMac( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, byte[] salt, int itCount, char[] password, diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/X509Principal.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/X509Principal.java index f7a96895a..dc3ef35c0 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/X509Principal.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/X509Principal.java @@ -129,7 +129,7 @@ public class X509Principal * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or * some such, converting it into an ordered set of name attributes. lookUp * should provide a table of lookups, indexed by lowercase only strings and - * yielding a DERObjectIdentifier, other than that OID. and numeric oids + * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids * will be processed automatically. ** If reverse is true, create the encoded version of the sequence starting diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/examples/PKCS12Example.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/examples/PKCS12Example.java deleted file mode 100644 index 6daf57bda..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/examples/PKCS12Example.java +++ /dev/null @@ -1,379 +0,0 @@ -package org.spongycastle.jce.examples; - -import java.io.FileOutputStream; -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Security; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.util.Date; -import java.util.Hashtable; -import java.util.Vector; - -import org.spongycastle.asn1.DERBMPString; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.x509.BasicConstraints; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.jce.PrincipalUtil; -import org.spongycastle.jce.X509Principal; -import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; -import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.spongycastle.x509.X509V1CertificateGenerator; -import org.spongycastle.x509.X509V3CertificateGenerator; -import org.spongycastle.x509.extension.AuthorityKeyIdentifierStructure; -import org.spongycastle.x509.extension.SubjectKeyIdentifierStructure; - -/** - * Example of how to set up a certificiate chain and a PKCS 12 store for - * a private individual - obviously you'll need to generate your own keys, - * and you may need to add a NetscapeCertType extension or add a key - * usage extension depending on your application, but you should get the - * idea! As always this is just an example... - */ -public class PKCS12Example -{ - static char[] passwd = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' }; - - static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator(); - static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); - - /** - * we generate the CA's certificate - */ - public static Certificate createMasterCert( - PublicKey pubKey, - PrivateKey privKey) - throws Exception - { - // - // signers name - // - String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // subjects name - the same as we are self signed. - // - String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // create the certificate - version 1 - // - - v1CertGen.setSerialNumber(BigInteger.valueOf(1)); - v1CertGen.setIssuerDN(new X509Principal(issuer)); - v1CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v1CertGen.setSubjectDN(new X509Principal(subject)); - v1CertGen.setPublicKey(pubKey); - v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - X509Certificate cert = v1CertGen.generate(privKey); - - cert.checkValidity(new Date()); - - cert.verify(pubKey); - - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; - - // - // this is actually optional - but if you want to have control - // over setting the friendly name this is the way to do it... - // - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_friendlyName, - new DERBMPString("Bouncy Primary Certificate")); - - return cert; - } - - /** - * we generate an intermediate certificate signed by our CA - */ - public static Certificate createIntermediateCert( - PublicKey pubKey, - PrivateKey caPrivKey, - X509Certificate caCert) - throws Exception - { - // - // subject name table. - // - Hashtable attrs = new Hashtable(); - Vector order = new Vector(); - - attrs.put(X509Principal.C, "AU"); - attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); - attrs.put(X509Principal.OU, "Bouncy Intermediate Certificate"); - attrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); - - order.addElement(X509Principal.C); - order.addElement(X509Principal.O); - order.addElement(X509Principal.OU); - order.addElement(X509Principal.EmailAddress); - - // - // create the certificate - version 3 - // - v3CertGen.reset(); - - v3CertGen.setSerialNumber(BigInteger.valueOf(2)); - v3CertGen.setIssuerDN(PrincipalUtil.getSubjectX509Principal(caCert)); - v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v3CertGen.setSubjectDN(new X509Principal(order, attrs)); - v3CertGen.setPublicKey(pubKey); - v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // - // extensions - // - v3CertGen.addExtension( - X509Extensions.SubjectKeyIdentifier, - false, - new SubjectKeyIdentifierStructure(pubKey)); - - v3CertGen.addExtension( - X509Extensions.AuthorityKeyIdentifier, - false, - new AuthorityKeyIdentifierStructure(caCert)); - - v3CertGen.addExtension( - X509Extensions.BasicConstraints, - true, - new BasicConstraints(0)); - - X509Certificate cert = v3CertGen.generate(caPrivKey); - - cert.checkValidity(new Date()); - - cert.verify(caCert.getPublicKey()); - - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; - - // - // this is actually optional - but if you want to have control - // over setting the friendly name this is the way to do it... - // - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_friendlyName, - new DERBMPString("Bouncy Intermediate Certificate")); - - return cert; - } - - /** - * we generate a certificate signed by our CA's intermediate certficate - */ - public static Certificate createCert( - PublicKey pubKey, - PrivateKey caPrivKey, - PublicKey caPubKey) - throws Exception - { - // - // signers name table. - // - Hashtable sAttrs = new Hashtable(); - Vector sOrder = new Vector(); - - sAttrs.put(X509Principal.C, "AU"); - sAttrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); - sAttrs.put(X509Principal.OU, "Bouncy Intermediate Certificate"); - sAttrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); - - sOrder.addElement(X509Principal.C); - sOrder.addElement(X509Principal.O); - sOrder.addElement(X509Principal.OU); - sOrder.addElement(X509Principal.EmailAddress); - - // - // subjects name table. - // - Hashtable attrs = new Hashtable(); - Vector order = new Vector(); - - attrs.put(X509Principal.C, "AU"); - attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); - attrs.put(X509Principal.L, "Melbourne"); - attrs.put(X509Principal.CN, "Eric H. Echidna"); - attrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); - - order.addElement(X509Principal.C); - order.addElement(X509Principal.O); - order.addElement(X509Principal.L); - order.addElement(X509Principal.CN); - order.addElement(X509Principal.EmailAddress); - - // - // create the certificate - version 3 - // - v3CertGen.reset(); - - v3CertGen.setSerialNumber(BigInteger.valueOf(3)); - v3CertGen.setIssuerDN(new X509Principal(sOrder, sAttrs)); - v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v3CertGen.setSubjectDN(new X509Principal(order, attrs)); - v3CertGen.setPublicKey(pubKey); - v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // - // add the extensions - // - v3CertGen.addExtension( - X509Extensions.SubjectKeyIdentifier, - false, - new SubjectKeyIdentifierStructure(pubKey)); - - v3CertGen.addExtension( - X509Extensions.AuthorityKeyIdentifier, - false, - new AuthorityKeyIdentifierStructure(caPubKey)); - - X509Certificate cert = v3CertGen.generate(caPrivKey); - - cert.checkValidity(new Date()); - - cert.verify(caPubKey); - - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)cert; - - // - // this is also optional - in the sense that if you leave this - // out the keystore will add it automatically, note though that - // for the browser to recognise the associated private key this - // you should at least use the pkcs_9_localKeyId OID and set it - // to the same as you do for the private key's localKeyId. - // - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_friendlyName, - new DERBMPString("Eric's Key")); - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_localKeyId, - new SubjectKeyIdentifierStructure(pubKey)); - - return cert; - } - - public static void main( - String[] args) - throws Exception - { - Security.addProvider(new BouncyCastleProvider()); - - // - // personal keys - // - RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16), - new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), - new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), - new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), - new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), - new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), - new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); - - // - // intermediate keys. - // - RSAPublicKeySpec intPubKeySpec = new RSAPublicKeySpec( - new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), - new BigInteger("ffff", 16)); - - - RSAPrivateCrtKeySpec intPrivKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16), - new BigInteger("ffff", 16), - new BigInteger("7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff", 16), - new BigInteger("ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649", 16), - new BigInteger("97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721", 16), - new BigInteger("6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f", 16), - new BigInteger("70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f", 16), - new BigInteger("e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d", 16)); - - // - // ca keys - // - RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16), - new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16), - new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16), - new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16), - new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16), - new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16), - new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16)); - - - - // - // set up the keys - // - KeyFactory fact = KeyFactory.getInstance("RSA", "SC"); - PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec); - PublicKey caPubKey = fact.generatePublic(caPubKeySpec); - PrivateKey intPrivKey = fact.generatePrivate(intPrivKeySpec); - PublicKey intPubKey = fact.generatePublic(intPubKeySpec); - PrivateKey privKey = fact.generatePrivate(privKeySpec); - PublicKey pubKey = fact.generatePublic(pubKeySpec); - - Certificate[] chain = new Certificate[3]; - - chain[2] = createMasterCert(caPubKey, caPrivKey); - chain[1] = createIntermediateCert(intPubKey, caPrivKey, (X509Certificate)chain[2]); - chain[0] = createCert(pubKey, intPrivKey, intPubKey); - - // - // add the friendly name for the private key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - - // - // this is also optional - in the sense that if you leave this - // out the keystore will add it automatically, note though that - // for the browser to recognise which certificate the private key - // is associated with you should at least use the pkcs_9_localKeyId - // OID and set it to the same as you do for the private key's - // corresponding certificate. - // - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_friendlyName, - new DERBMPString("Eric's Key")); - bagAttr.setBagAttribute( - PKCSObjectIdentifiers.pkcs_9_at_localKeyId, - new SubjectKeyIdentifierStructure(pubKey)); - - // - // store the key and the certificate chain - // - KeyStore store = KeyStore.getInstance("PKCS12", "SC"); - - store.load(null, null); - - // - // if you haven't set the friendly name and local key id above - // the name below will be the name of the key - // - store.setKeyEntry("Eric's Key", privKey, null, chain); - - FileOutputStream fOut = new FileOutputStream("id.p12"); - - store.store(fOut, passwd); - - fOut.close(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/BouncyCastleProvider.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/BouncyCastleProvider.java index 245e46cd5..95d68e731 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/BouncyCastleProvider.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/BouncyCastleProvider.java @@ -44,7 +44,7 @@ import org.spongycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { - private static String info = "BouncyCastle Security Provider v1.50"; + private static String info = "BouncyCastle Security Provider v1.51"; public static final String PROVIDER_NAME = "SC"; @@ -117,7 +117,7 @@ public final class BouncyCastleProvider extends Provider */ public BouncyCastleProvider() { - super(PROVIDER_NAME, 1.50, info); + super(PROVIDER_NAME, 1.51, info); AccessController.doPrivileged(new PrivilegedAction() { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/CertPathValidatorUtilities.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/CertPathValidatorUtilities.java index 7f13a2e98..294155225 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/CertPathValidatorUtilities.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/CertPathValidatorUtilities.java @@ -38,16 +38,16 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Enumerated; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1OutputStream; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DEREnumerated; -import org.spongycastle.asn1.DERGeneralizedTime; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.isismtt.ISISMTTObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -455,7 +455,7 @@ public class CertPathValidatorUtilities protected static boolean processCertD1i( int index, List[] policyNodes, - DERObjectIdentifier pOid, + ASN1ObjectIdentifier pOid, Set pq) { List policyNodeVec = policyNodes[index - 1]; @@ -490,7 +490,7 @@ public class CertPathValidatorUtilities protected static void processCertD1ii( int index, List[] policyNodes, - DERObjectIdentifier _poid, + ASN1ObjectIdentifier _poid, Set _pq) { List policyNodeVec = policyNodes[index - 1]; @@ -1017,12 +1017,12 @@ public class CertPathValidatorUtilities } } - DEREnumerated reasonCode = null; + ASN1Enumerated reasonCode = null; if (crl_entry.hasExtensions()) { try { - reasonCode = DEREnumerated + reasonCode = ASN1Enumerated .getInstance(CertPathValidatorUtilities .getExtensionValue(crl_entry, X509Extension.reasonCode.getId())); @@ -1243,13 +1243,13 @@ public class CertPathValidatorUtilities { if (index - 1 == 0) { - DERGeneralizedTime dateOfCertgen = null; + ASN1GeneralizedTime dateOfCertgen = null; try { byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId()); if (extBytes != null) { - dateOfCertgen = DERGeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); + dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); } } catch (IOException e) diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPrivateKey.java index 5fca7fbdd..e76441741 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPrivateKey.java @@ -12,10 +12,9 @@ import javax.crypto.spec.DHPrivateKeySpec; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.DHParameter; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; @@ -61,8 +60,8 @@ public class JCEDHPrivateKey throws IOException { ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters()); - DERInteger derX = DERInteger.getInstance(info.parsePrivateKey()); - DERObjectIdentifier id = info.getAlgorithmId().getAlgorithm(); + ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey()); + ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm(); this.info = info; this.x = derX.getValue(); @@ -129,7 +128,7 @@ public class JCEDHPrivateKey return info.getEncoded(ASN1Encoding.DER); } - PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new DERInteger(getX())); + PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new ASN1Integer(getX())); return info.getEncoded(ASN1Encoding.DER); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPublicKey.java index ac8500962..c53e89d67 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEDHPublicKey.java @@ -9,9 +9,9 @@ import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.DHParameter; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -64,10 +64,10 @@ public class JCEDHPublicKey { this.info = info; - DERInteger derY; + ASN1Integer derY; try { - derY = (DERInteger)info.parsePublicKey(); + derY = (ASN1Integer)info.parsePublicKey(); } catch (IOException e) { @@ -77,7 +77,7 @@ public class JCEDHPublicKey this.y = derY.getValue(); ASN1Sequence seq = ASN1Sequence.getInstance(info.getAlgorithmId().getParameters()); - DERObjectIdentifier id = info.getAlgorithmId().getAlgorithm(); + ASN1ObjectIdentifier id = info.getAlgorithmId().getAlgorithm(); // we need the PKCS check to handle older keys marked with the X9 oid. if (id.equals(PKCSObjectIdentifiers.dhKeyAgreement) || isPKCSParam(seq)) @@ -122,7 +122,7 @@ public class JCEDHPublicKey return KeyUtil.getEncodedSubjectPublicKeyInfo(info); } - return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new DERInteger(y)); + return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.dhKeyAgreement, new DHParameter(dhSpec.getP(), dhSpec.getG(), dhSpec.getL())), new ASN1Integer(y)); } public DHParameterSpec getParams() @@ -147,8 +147,8 @@ public class JCEDHPublicKey return false; } - DERInteger l = DERInteger.getInstance(seq.getObjectAt(2)); - DERInteger p = DERInteger.getInstance(seq.getObjectAt(0)); + ASN1Integer l = ASN1Integer.getInstance(seq.getObjectAt(2)); + ASN1Integer p = ASN1Integer.getInstance(seq.getObjectAt(0)); if (l.getValue().compareTo(BigInteger.valueOf(p.getValue().bitLength())) > 0) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPrivateKey.java index f4acffcde..abb0364b0 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPrivateKey.java @@ -13,13 +13,12 @@ import java.util.Enumeration; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.cryptopro.ECGOST3410NamedCurves; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; @@ -250,9 +249,9 @@ public class JCEECPrivateKey } ASN1Encodable privKey = info.parsePrivateKey(); - if (privKey instanceof DERInteger) + if (privKey instanceof ASN1Integer) { - DERInteger derD = DERInteger.getInstance(privKey); + ASN1Integer derD = ASN1Integer.getInstance(privKey); this.d = derD.getValue(); } @@ -292,10 +291,10 @@ public class JCEECPrivateKey if (ecSpec instanceof ECNamedCurveSpec) { - DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); if (curveOid == null) // guess it's the OID { - curveOid = new DERObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); } params = new X962Parameters(curveOid); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPublicKey.java index 08c640dbb..7f550e05d 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEECPublicKey.java @@ -38,6 +38,8 @@ import org.spongycastle.jce.interfaces.ECPointEncoder; import org.spongycastle.jce.spec.ECNamedCurveParameterSpec; import org.spongycastle.jce.spec.ECNamedCurveSpec; import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.custom.sec.SecP256K1Point; +import org.spongycastle.math.ec.custom.sec.SecP256R1Point; public class JCEECPublicKey implements ECPublicKey, org.spongycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -439,14 +441,7 @@ public class JCEECPublicKey { if (ecSpec == null) { - if (q instanceof org.spongycastle.math.ec.ECPoint.Fp) - { - return new org.spongycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord()); - } - else - { - return new org.spongycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord()); - } + return q.getDetachedPoint(); } return q; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPrivateKey.java index 096da0cf4..4d98792c8 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPrivateKey.java @@ -13,8 +13,6 @@ import javax.crypto.spec.DHPrivateKeySpec; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; @@ -74,8 +72,8 @@ public class JCEElGamalPrivateKey PrivateKeyInfo info) throws IOException { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)info.getAlgorithmId().getParameters()); - DERInteger derX = ASN1Integer.getInstance(info.parsePrivateKey()); + ElGamalParameter params = ElGamalParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters()); + ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey()); this.x = derX.getValue(); this.elSpec = new ElGamalParameterSpec(params.getP(), params.getG()); @@ -111,7 +109,7 @@ public class JCEElGamalPrivateKey */ public byte[] getEncoded() { - return KeyUtil.getEncodedPrivateKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new DERInteger(getX())); + return KeyUtil.getEncodedPrivateKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new ASN1Integer(getX())); } public ElGamalParameterSpec getParameters() diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPublicKey.java index 83b24629a..208444562 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEElGamalPublicKey.java @@ -9,8 +9,7 @@ import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.oiw.ElGamalParameter; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -75,12 +74,12 @@ public class JCEElGamalPublicKey JCEElGamalPublicKey( SubjectPublicKeyInfo info) { - ElGamalParameter params = new ElGamalParameter((ASN1Sequence)info.getAlgorithmId().getParameters()); - DERInteger derY = null; + ElGamalParameter params = ElGamalParameter.getInstance(info.getAlgorithm().getParameters()); + ASN1Integer derY = null; try { - derY = (DERInteger)info.parsePublicKey(); + derY = (ASN1Integer)info.parsePublicKey(); } catch (IOException e) { @@ -103,7 +102,7 @@ public class JCEElGamalPublicKey public byte[] getEncoded() { - return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new DERInteger(y)); + return KeyUtil.getEncodedSubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(elSpec.getP(), elSpec.getG())), new ASN1Integer(y)); } public ElGamalParameterSpec getParameters() diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEStreamCipher.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEStreamCipher.java index e395045c5..64346b2ac 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEStreamCipher.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JCEStreamCipher.java @@ -28,15 +28,12 @@ import javax.crypto.spec.RC5ParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; -import org.spongycastle.crypto.BlockCipher; import org.spongycastle.crypto.CipherParameters; import org.spongycastle.crypto.DataLengthException; -import org.spongycastle.crypto.StreamBlockCipher; import org.spongycastle.crypto.StreamCipher; import org.spongycastle.crypto.engines.BlowfishEngine; import org.spongycastle.crypto.engines.DESEngine; import org.spongycastle.crypto.engines.DESedeEngine; -import org.spongycastle.crypto.engines.RC4Engine; import org.spongycastle.crypto.engines.SkipjackEngine; import org.spongycastle.crypto.engines.TwofishEngine; import org.spongycastle.crypto.modes.CFBBlockCipher; @@ -78,15 +75,6 @@ public class JCEStreamCipher cipher = engine; this.ivLength = ivLength; } - - protected JCEStreamCipher( - BlockCipher engine, - int ivLength) - { - this.ivLength = ivLength; - - cipher = new StreamBlockCipher(engine); - } protected int engineGetBlockSize() { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPrivateKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPrivateKey.java index 68781681c..3a9da836e 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPrivateKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPrivateKey.java @@ -14,8 +14,6 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.DSAParameter; @@ -57,7 +55,7 @@ public class JDKDSAPrivateKey throws IOException { DSAParameter params = DSAParameter.getInstance(info.getPrivateKeyAlgorithm().getParameters()); - DERInteger derX = ASN1Integer.getInstance(info.parsePrivateKey()); + ASN1Integer derX = ASN1Integer.getInstance(info.parsePrivateKey()); this.x = derX.getValue(); this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG()); @@ -95,7 +93,7 @@ public class JDKDSAPrivateKey { try { - PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new DERInteger(getX())); + PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new ASN1Integer(getX())); return info.getEncoded(ASN1Encoding.DER); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPublicKey.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPublicKey.java index 78d1ca09d..78e8c09ef 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPublicKey.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/JDKDSAPublicKey.java @@ -11,8 +11,7 @@ import java.security.spec.DSAPublicKeySpec; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERNull; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.DSAParameter; @@ -61,11 +60,11 @@ public class JDKDSAPublicKey SubjectPublicKeyInfo info) { - DERInteger derY; + ASN1Integer derY; try { - derY = (DERInteger)info.parsePublicKey(); + derY = (ASN1Integer)info.parsePublicKey(); } catch (IOException e) { @@ -103,10 +102,10 @@ public class JDKDSAPublicKey { if (dsaSpec == null) { - return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new DERInteger(y)).getEncoded(ASN1Encoding.DER); + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER); } - return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new DERInteger(y)).getEncoded(ASN1Encoding.DER); + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG())), new ASN1Integer(y)).getEncoded(ASN1Encoding.DER); } catch (IOException e) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java index 962b2c4fc..df0e24675 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java @@ -21,7 +21,7 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.jce.exception.ExtCertPathValidatorException; import org.spongycastle.x509.ExtendedPKIXParameters; @@ -218,7 +218,7 @@ public class PKIXCertPathValidatorSpi throw new ExtCertPathValidatorException( "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1); } - DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId(); + ASN1ObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getAlgorithm(); ASN1Encodable workingPublicKeyParameters = workingAlgId.getParameters(); // @@ -371,7 +371,7 @@ public class PKIXCertPathValidatorSpi workingAlgId = CertPathValidatorUtilities.getAlgorithmIdentifier(workingPublicKey); // (f) - workingPublicKeyAlgorithm = workingAlgId.getObjectId(); + workingPublicKeyAlgorithm = workingAlgId.getAlgorithm(); // (e) workingPublicKeyParameters = workingAlgId.getParameters(); } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java index 8e00d3af6..a8961570c 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java @@ -33,11 +33,11 @@ import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.BasicConstraints; import org.spongycastle.asn1.x509.CRLDistPoint; @@ -893,8 +893,8 @@ public class RFC3280CertPathUtilities for (int j = 0; j < mappings.size(); j++) { ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j); - String id_p = ((DERObjectIdentifier)mapping.getObjectAt(0)).getId(); - String sd_p = ((DERObjectIdentifier)mapping.getObjectAt(1)).getId(); + String id_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(0)).getId(); + String sd_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(1)).getId(); Set tmp; if (!m_idp.containsKey(id_p)) @@ -1072,14 +1072,14 @@ public class RFC3280CertPathUtilities for (int j = 0; j < mappings.size(); j++) { - DERObjectIdentifier issuerDomainPolicy = null; - DERObjectIdentifier subjectDomainPolicy = null; + ASN1ObjectIdentifier issuerDomainPolicy = null; + ASN1ObjectIdentifier subjectDomainPolicy = null; try { ASN1Sequence mapping = DERSequence.getInstance(mappings.getObjectAt(j)); - issuerDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(0)); - subjectDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(1)); + issuerDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(0)); + subjectDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(1)); } catch (Exception e) { @@ -1286,7 +1286,7 @@ public class RFC3280CertPathUtilities while (e.hasMoreElements()) { PolicyInformation pInfo = PolicyInformation.getInstance(e.nextElement()); - DERObjectIdentifier pOid = pInfo.getPolicyIdentifier(); + ASN1ObjectIdentifier pOid = pInfo.getPolicyIdentifier(); pols.add(pOid.getId()); @@ -1365,9 +1365,9 @@ public class RFC3280CertPathUtilities { _policy = (String)_tmp; } - else if (_tmp instanceof DERObjectIdentifier) + else if (_tmp instanceof ASN1ObjectIdentifier) { - _policy = ((DERObjectIdentifier)_tmp).getId(); + _policy = ((ASN1ObjectIdentifier)_tmp).getId(); } else { @@ -1567,7 +1567,7 @@ public class RFC3280CertPathUtilities ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement()); if (constraint.getTagNo() == 0) { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < explicitPolicy) { return tmpInt; @@ -1621,7 +1621,7 @@ public class RFC3280CertPathUtilities ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement()); if (constraint.getTagNo() == 1) { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < policyMapping) { return tmpInt; @@ -2033,10 +2033,10 @@ public class RFC3280CertPathUtilities // // (j) // - DERInteger iap = null; + ASN1Integer iap = null; try { - iap = DERInteger.getInstance(CertPathValidatorUtilities.getExtensionValue(cert, + iap = ASN1Integer.getInstance(CertPathValidatorUtilities.getExtensionValue(cert, RFC3280CertPathUtilities.INHIBIT_ANY_POLICY)); } catch (Exception e) @@ -2339,7 +2339,7 @@ public class RFC3280CertPathUtilities case 0: try { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); } catch (Exception e) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509AttrCertParser.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509AttrCertParser.java index 6a44ade19..2ee524da4 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509AttrCertParser.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509AttrCertParser.java @@ -8,10 +8,10 @@ import java.util.Collection; import java.util.List; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.pkcs.SignedData; import org.spongycastle.x509.X509AttributeCertificate; @@ -36,7 +36,7 @@ public class X509AttrCertParser ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() > 1 - && seq.getObjectAt(0) instanceof DERObjectIdentifier) + && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier) { if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CRLParser.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CRLParser.java index 53aec7a32..cf066357d 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CRLParser.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CRLParser.java @@ -10,10 +10,10 @@ import java.util.Collection; import java.util.List; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.pkcs.SignedData; import org.spongycastle.asn1.x509.CertificateList; @@ -37,7 +37,7 @@ public class X509CRLParser ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() > 1 - && seq.getObjectAt(0) instanceof DERObjectIdentifier) + && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier) { if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CertParser.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CertParser.java index cc6752980..455310cf7 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CertParser.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509CertParser.java @@ -10,10 +10,10 @@ import java.util.Collection; import java.util.List; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.pkcs.SignedData; import org.spongycastle.x509.X509StreamParserSpi; @@ -36,7 +36,7 @@ public class X509CertParser ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); if (seq.size() > 1 - && seq.getObjectAt(0) instanceof DERObjectIdentifier) + && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier) { if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509SignatureUtil.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509SignatureUtil.java index 030d52016..c1beb466b 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509SignatureUtil.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/provider/X509SignatureUtil.java @@ -11,9 +11,9 @@ import java.security.spec.PSSParameterSpec; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Null; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -66,21 +66,21 @@ class X509SignatureUtil if (params != null && !derNull.equals(params)) { - if (sigAlgId.getObjectId().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) + if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) { RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params); - return getDigestAlgName(rsaParams.getHashAlgorithm().getObjectId()) + "withRSAandMGF1"; + return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1"; } - if (sigAlgId.getObjectId().equals(X9ObjectIdentifiers.ecdsa_with_SHA2)) + if (sigAlgId.getAlgorithm().equals(X9ObjectIdentifiers.ecdsa_with_SHA2)) { ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params); - return getDigestAlgName((DERObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA"; + return getDigestAlgName(ASN1ObjectIdentifier.getInstance(ecDsaParams.getObjectAt(0))) + "withECDSA"; } } - return sigAlgId.getObjectId().getId(); + return sigAlgId.getAlgorithm().getId(); } /** @@ -88,7 +88,7 @@ class X509SignatureUtil * representations rather the the algorithm identifier (if possible). */ private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveParameterSpec.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveParameterSpec.java index e7ef6c20b..f10a0b414 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveParameterSpec.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveParameterSpec.java @@ -7,9 +7,9 @@ import org.spongycastle.math.ec.ECPoint; /** * specification signifying that the curve parameters can also be - * refered to by name. + * referred to by name. *
- * If you are using JDK 1.5 you should be looking at ECNamedCurveSpec. + * If you are using JDK 1.5 you should be looking at {@link ECNamedCurveSpec}. */ public class ECNamedCurveParameterSpec extends ECParameterSpec diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveSpec.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveSpec.java index 68b64a2a0..681d70705 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveSpec.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/ECNamedCurveSpec.java @@ -6,6 +6,7 @@ import java.security.spec.ECFieldFp; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; +import org.spongycastle.math.ec.ECAlgorithms; import org.spongycastle.math.ec.ECCurve; /** @@ -21,9 +22,9 @@ public class ECNamedCurveSpec ECCurve curve, byte[] seed) { - if (curve instanceof ECCurve.Fp) + if (ECAlgorithms.isFpCurve(curve)) { - return new EllipticCurve(new ECFieldFp(((ECCurve.Fp)curve).getQ()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); + return new EllipticCurve(new ECFieldFp(curve.getField().getCharacteristic()), curve.getA().toBigInteger(), curve.getB().toBigInteger(), seed); } else { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/IESParameterSpec.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/IESParameterSpec.java index e590a7690..d3fc08355 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/IESParameterSpec.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/jce/spec/IESParameterSpec.java @@ -2,6 +2,8 @@ package org.spongycastle.jce.spec; import java.security.spec.AlgorithmParameterSpec; +import org.spongycastle.util.Arrays; + /** * Parameter spec for an integrated encryptor, as in IEEE P1363a */ @@ -12,6 +14,7 @@ public class IESParameterSpec private byte[] encoding; private int macKeySize; private int cipherKeySize; + private byte[] nonce; /** @@ -43,6 +46,25 @@ public class IESParameterSpec byte[] encoding, int macKeySize, int cipherKeySize) + { + this(derivation, encoding, macKeySize, cipherKeySize, null); + } + + /** + * Set the IES engine parameters. + * + * @param derivation the optional derivation vector for the KDF. + * @param encoding the optional encoding vector for the KDF. + * @param macKeySize the key size (in bits) for the MAC. + * @param cipherKeySize the key size (in bits) for the block cipher. + * @param nonce an IV to use initialising the block cipher. + */ + public IESParameterSpec( + byte[] derivation, + byte[] encoding, + int macKeySize, + int cipherKeySize, + byte[] nonce) { if (derivation != null) { @@ -66,15 +88,15 @@ public class IESParameterSpec this.macKeySize = macKeySize; this.cipherKeySize = cipherKeySize; + this.nonce = Arrays.clone(nonce); } - /** * return the derivation vector. */ public byte[] getDerivationV() { - return derivation; + return Arrays.clone(derivation); } /** @@ -82,7 +104,7 @@ public class IESParameterSpec */ public byte[] getEncodingV() { - return encoding; + return Arrays.clone(encoding); } /** @@ -101,4 +123,13 @@ public class IESParameterSpec return cipherKeySize; } + /** + * Return the nonce (IV) value to be associated with message. + * + * @return block cipher IV for message. + */ + public byte[] getNonce() + { + return Arrays.clone(nonce); + } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPResp.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPResp.java deleted file mode 100644 index f8d00f3bb..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPResp.java +++ /dev/null @@ -1,366 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertStore; -import java.security.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CollectionCertStoreParameters; -import java.security.cert.X509Certificate; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.ocsp.BasicOCSPResponse; -import org.spongycastle.asn1.ocsp.ResponseData; -import org.spongycastle.asn1.ocsp.SingleResponse; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -/** - *
- * BasicOCSPResponse ::= SEQUENCE { - * tbsResponseData ResponseData, - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } - *- * - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class BasicOCSPResp - implements java.security.cert.X509Extension -{ - BasicOCSPResponse resp; - ResponseData data; - X509Certificate[] chain = null; - - public BasicOCSPResp( - BasicOCSPResponse resp) - { - this.resp = resp; - this.data = resp.getTbsResponseData(); - } - - /** - * Return the DER encoding of the tbsResponseData field. - * @return DER encoding of tbsResponseData - * @throws OCSPException in the event of an encoding error. - */ - public byte[] getTBSResponseData() - throws OCSPException - { - try - { - return resp.getTbsResponseData().getEncoded(); - } - catch (IOException e) - { - throw new OCSPException("problem encoding tbsResponseData", e); - } - } - - public int getVersion() - { - return data.getVersion().getValue().intValue() + 1; - } - - public RespID getResponderId() - { - return new RespID(data.getResponderID()); - } - - public Date getProducedAt() - { - try - { - return data.getProducedAt().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException:" + e.getMessage()); - } - } - - public SingleResp[] getResponses() - { - ASN1Sequence s = data.getResponses(); - SingleResp[] rs = new SingleResp[s.size()]; - - for (int i = 0; i != rs.length; i++) - { - rs[i] = new SingleResp(SingleResponse.getInstance(s.getObjectAt(i))); - } - - return rs; - } - - public X509Extensions getResponseExtensions() - { - return X509Extensions.getInstance(data.getResponseExtensions()); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getResponseExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getResponseExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } - - public String getSignatureAlgName() - { - return OCSPUtil.getAlgorithmName(resp.getSignatureAlgorithm().getObjectId()); - } - - public String getSignatureAlgOID() - { - return resp.getSignatureAlgorithm().getObjectId().getId(); - } - - /** - * @deprecated RespData class is no longer required as all functionality is - * available on this class. - * @return the RespData object - */ - public RespData getResponseData() - { - return new RespData(resp.getTbsResponseData()); - } - - public byte[] getSignature() - { - return resp.getSignature().getBytes(); - } - - private List getCertList( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = new ArrayList(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - CertificateFactory cf; - - try - { - cf = OCSPUtil.createX509CertificateFactory(provider); - } - catch (CertificateException ex) - { - throw new OCSPException("can't get certificate factory.", ex); - } - - // - // load the certificates and revocation lists if we have any - // - ASN1Sequence s = resp.getCerts(); - - if (s != null) - { - Enumeration e = s.getObjects(); - - while (e.hasMoreElements()) - { - try - { - aOut.writeObject((ASN1Encodable)e.nextElement()); - - certs.add(cf.generateCertificate( - new ByteArrayInputStream(bOut.toByteArray()))); - } - catch (IOException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - catch (CertificateException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - - bOut.reset(); - } - } - - return certs; - } - - public X509Certificate[] getCerts( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = getCertList(provider); - - return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); - } - - /** - * Return the certificates, if any associated with the response. - * @param type type of CertStore to create - * @param provider provider to use - * @return a CertStore, possibly empty - * @throws NoSuchAlgorithmException - * @throws NoSuchProviderException - * @throws OCSPException - */ - public CertStore getCertificates( - String type, - String provider) - throws NoSuchAlgorithmException, NoSuchProviderException, OCSPException - { - try - { - CertStoreParameters params = new CollectionCertStoreParameters(this.getCertList(provider)); - return OCSPUtil.createCertStoreInstance(type, params, provider); - } - catch (InvalidAlgorithmParameterException e) - { - throw new OCSPException("can't setup the CertStore", e); - } - } - - /** - * verify the signature against the tbsResponseData object we contain. - */ - public boolean verify( - PublicKey key, - String sigProvider) - throws OCSPException, NoSuchProviderException - { - try - { - Signature signature = OCSPUtil.createSignatureInstance(this.getSignatureAlgName(), sigProvider); - - signature.initVerify(key); - - signature.update(resp.getTbsResponseData().getEncoded(ASN1Encoding.DER)); - - return signature.verify(this.getSignature()); - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (Exception e) - { - throw new OCSPException("exception processing sig: " + e, e); - } - } - - /** - * return the ASN.1 encoded representation of this object. - */ - public byte[] getEncoded() - throws IOException - { - return resp.getEncoded(); - } - - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - - if (!(o instanceof BasicOCSPResp)) - { - return false; - } - - BasicOCSPResp r = (BasicOCSPResp)o; - - return resp.equals(r.resp); - } - - public int hashCode() - { - return resp.hashCode(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPRespGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPRespGenerator.java deleted file mode 100644 index 5c62b45f2..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/BasicOCSPRespGenerator.java +++ /dev/null @@ -1,344 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1GeneralizedTime; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERGeneralizedTime; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.ocsp.BasicOCSPResponse; -import org.spongycastle.asn1.ocsp.CertStatus; -import org.spongycastle.asn1.ocsp.ResponseData; -import org.spongycastle.asn1.ocsp.RevokedInfo; -import org.spongycastle.asn1.ocsp.SingleResponse; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.CRLReason; -import org.spongycastle.asn1.x509.X509CertificateStructure; -import org.spongycastle.asn1.x509.X509Extensions; - -/** - * Generator for basic OCSP response objects. - * - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class BasicOCSPRespGenerator -{ - private List list = new ArrayList(); - private X509Extensions responseExtensions = null; - private RespID responderID; - - private class ResponseObject - { - CertificateID certId; - CertStatus certStatus; - DERGeneralizedTime thisUpdate; - DERGeneralizedTime nextUpdate; - X509Extensions extensions; - - public ResponseObject( - CertificateID certId, - CertificateStatus certStatus, - Date thisUpdate, - Date nextUpdate, - X509Extensions extensions) - { - this.certId = certId; - - if (certStatus == null) - { - this.certStatus = new CertStatus(); - } - else if (certStatus instanceof UnknownStatus) - { - this.certStatus = new CertStatus(2, DERNull.INSTANCE); - } - else - { - RevokedStatus rs = (RevokedStatus)certStatus; - - if (rs.hasRevocationReason()) - { - this.certStatus = new CertStatus( - new RevokedInfo(new ASN1GeneralizedTime(rs.getRevocationTime()), CRLReason.lookup(rs.getRevocationReason()))); - } - else - { - this.certStatus = new CertStatus( - new RevokedInfo(new ASN1GeneralizedTime(rs.getRevocationTime()), null)); - } - } - - this.thisUpdate = new DERGeneralizedTime(thisUpdate); - - if (nextUpdate != null) - { - this.nextUpdate = new DERGeneralizedTime(nextUpdate); - } - else - { - this.nextUpdate = null; - } - - this.extensions = extensions; - } - - public SingleResponse toResponse() - throws Exception - { - return new SingleResponse(certId.toASN1Object(), certStatus, thisUpdate, nextUpdate, extensions); - } - } - - /** - * basic constructor - */ - public BasicOCSPRespGenerator( - RespID responderID) - { - this.responderID = responderID; - } - - /** - * construct with the responderID to be the SHA-1 keyHash of the passed in public key. - */ - public BasicOCSPRespGenerator( - PublicKey key) - throws OCSPException - { - this.responderID = new RespID(key); - } - - /** - * Add a response for a particular Certificate ID. - * - * @param certID certificate ID details - * @param certStatus status of the certificate - null if okay - */ - public void addResponse( - CertificateID certID, - CertificateStatus certStatus) - { - list.add(new ResponseObject(certID, certStatus, new Date(), null, null)); - } - - /** - * Add a response for a particular Certificate ID. - * - * @param certID certificate ID details - * @param certStatus status of the certificate - null if okay - * @param singleExtensions optional extensions - */ - public void addResponse( - CertificateID certID, - CertificateStatus certStatus, - X509Extensions singleExtensions) - { - list.add(new ResponseObject(certID, certStatus, new Date(), null, singleExtensions)); - } - - /** - * Add a response for a particular Certificate ID. - * - * @param certID certificate ID details - * @param nextUpdate date when next update should be requested - * @param certStatus status of the certificate - null if okay - * @param singleExtensions optional extensions - */ - public void addResponse( - CertificateID certID, - CertificateStatus certStatus, - Date nextUpdate, - X509Extensions singleExtensions) - { - list.add(new ResponseObject(certID, certStatus, new Date(), nextUpdate, singleExtensions)); - } - - /** - * Add a response for a particular Certificate ID. - * - * @param certID certificate ID details - * @param thisUpdate date this response was valid on - * @param nextUpdate date when next update should be requested - * @param certStatus status of the certificate - null if okay - * @param singleExtensions optional extensions - */ - public void addResponse( - CertificateID certID, - CertificateStatus certStatus, - Date thisUpdate, - Date nextUpdate, - X509Extensions singleExtensions) - { - list.add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions)); - } - - /** - * Set the extensions for the response. - * - * @param responseExtensions the extension object to carry. - */ - public void setResponseExtensions( - X509Extensions responseExtensions) - { - this.responseExtensions = responseExtensions; - } - - private BasicOCSPResp generateResponse( - String signatureName, - PrivateKey key, - X509Certificate[] chain, - Date producedAt, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException - { - Iterator it = list.iterator(); - DERObjectIdentifier signingAlgorithm; - - try - { - signingAlgorithm = OCSPUtil.getAlgorithmOID(signatureName); - } - catch (Exception e) - { - throw new IllegalArgumentException("unknown signing algorithm specified"); - } - - ASN1EncodableVector responses = new ASN1EncodableVector(); - - while (it.hasNext()) - { - try - { - responses.add(((ResponseObject)it.next()).toResponse()); - } - catch (Exception e) - { - throw new OCSPException("exception creating Request", e); - } - } - - ResponseData tbsResp = new ResponseData(responderID.toASN1Object(), new DERGeneralizedTime(producedAt), new DERSequence(responses), responseExtensions); - - Signature sig = null; - - try - { - sig = OCSPUtil.createSignatureInstance(signatureName, provider); - if (random != null) - { - sig.initSign(key, random); - } - else - { - sig.initSign(key); - } - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (GeneralSecurityException e) - { - throw new OCSPException("exception creating signature: " + e, e); - } - - DERBitString bitSig = null; - - try - { - sig.update(tbsResp.getEncoded(ASN1Encoding.DER)); - - bitSig = new DERBitString(sig.sign()); - } - catch (Exception e) - { - throw new OCSPException("exception processing TBSRequest: " + e, e); - } - - AlgorithmIdentifier sigAlgId = OCSPUtil.getSigAlgID(signingAlgorithm); - - DERSequence chainSeq = null; - if (chain != null && chain.length > 0) - { - ASN1EncodableVector v = new ASN1EncodableVector(); - try - { - for (int i = 0; i != chain.length; i++) - { - v.add(new X509CertificateStructure( - (ASN1Sequence)ASN1Primitive.fromByteArray(chain[i].getEncoded()))); - } - } - catch (IOException e) - { - throw new OCSPException("error processing certs", e); - } - catch (CertificateEncodingException e) - { - throw new OCSPException("error encoding certs", e); - } - - chainSeq = new DERSequence(v); - } - - return new BasicOCSPResp(new BasicOCSPResponse(tbsResp, sigAlgId, bitSig, chainSeq)); - } - - public BasicOCSPResp generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - Date thisUpdate, - String provider) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - return generate(signingAlgorithm, key, chain, thisUpdate, provider, null); - } - - public BasicOCSPResp generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - Date producedAt, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - if (signingAlgorithm == null) - { - throw new IllegalArgumentException("no signing algorithm specified"); - } - - return generateResponse(signingAlgorithm, key, chain, producedAt, provider, random); - } - - /** - * Return an iterator of the signature names supported by the generator. - * - * @return an iterator containing recognised names. - */ - public Iterator getSignatureAlgNames() - { - return OCSPUtil.getAlgNames(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateID.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateID.java deleted file mode 100644 index cb86c29d5..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateID.java +++ /dev/null @@ -1,170 +0,0 @@ -package org.spongycastle.ocsp; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.PublicKey; -import java.security.cert.X509Certificate; - -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.ocsp.CertID; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.jce.PrincipalUtil; -import org.spongycastle.jce.X509Principal; - -public class CertificateID -{ - public static final String HASH_SHA1 = "1.3.14.3.2.26"; - - private final CertID id; - - public CertificateID( - CertID id) - { - if (id == null) - { - throw new IllegalArgumentException("'id' cannot be null"); - } - this.id = id; - } - - /** - * create from an issuer certificate and the serial number of the - * certificate it signed. - * - * @param hashAlgorithm hash algorithm to use - * @param issuerCert issuing certificate - * @param number serial number - * @param provider provider to use for hashAlgorithm, null if the default one should be used. - * - * @exception OCSPException if any problems occur creating the id fields. - */ - public CertificateID( - String hashAlgorithm, - X509Certificate issuerCert, - BigInteger number, - String provider) - throws OCSPException - { - AlgorithmIdentifier hashAlg = new AlgorithmIdentifier( - new DERObjectIdentifier(hashAlgorithm), DERNull.INSTANCE); - - this.id = createCertID(hashAlg, issuerCert, new ASN1Integer(number), provider); - } - - /** - * create using the BC provider - */ - public CertificateID( - String hashAlgorithm, - X509Certificate issuerCert, - BigInteger number) - throws OCSPException - { - this(hashAlgorithm, issuerCert, number, "SC"); - } - - public String getHashAlgOID() - { - return id.getHashAlgorithm().getObjectId().getId(); - } - - public byte[] getIssuerNameHash() - { - return id.getIssuerNameHash().getOctets(); - } - - public byte[] getIssuerKeyHash() - { - return id.getIssuerKeyHash().getOctets(); - } - - /** - * return the serial number for the certificate associated - * with this request. - */ - public BigInteger getSerialNumber() - { - return id.getSerialNumber().getValue(); - } - - public boolean matchesIssuer(X509Certificate issuerCert, String provider) - throws OCSPException - { - return createCertID(id.getHashAlgorithm(), issuerCert, id.getSerialNumber(), provider) - .equals(id); - } - - public CertID toASN1Object() - { - return id; - } - - public boolean equals( - Object o) - { - if (!(o instanceof CertificateID)) - { - return false; - } - - CertificateID obj = (CertificateID)o; - - return id.toASN1Primitive().equals(obj.id.toASN1Primitive()); - } - - public int hashCode() - { - return id.toASN1Primitive().hashCode(); - } - - /** - * Create a new CertificateID for a new serial number derived from a previous one - * calculated for the same CA certificate. - * - * @param original the previously calculated CertificateID for the CA. - * @param newSerialNumber the serial number for the new certificate of interest. - * - * @return a new CertificateID for newSerialNumber - */ - public static CertificateID deriveCertificateID(CertificateID original, BigInteger newSerialNumber) - { - return new CertificateID(new CertID(original.id.getHashAlgorithm(), original.id.getIssuerNameHash(), original.id.getIssuerKeyHash(), new ASN1Integer(newSerialNumber))); - } - - private static CertID createCertID(AlgorithmIdentifier hashAlg, X509Certificate issuerCert, - ASN1Integer serialNumber, String provider) - throws OCSPException - { - try - { - MessageDigest digest = OCSPUtil.createDigestInstance(hashAlg.getAlgorithm() .getId(), - provider); - - X509Principal issuerName = PrincipalUtil.getSubjectX509Principal(issuerCert); - - digest.update(issuerName.getEncoded()); - - ASN1OctetString issuerNameHash = new DEROctetString(digest.digest()); - PublicKey issuerKey = issuerCert.getPublicKey(); - - ASN1InputStream aIn = new ASN1InputStream(issuerKey.getEncoded()); - SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject()); - - digest.update(info.getPublicKeyData().getBytes()); - - ASN1OctetString issuerKeyHash = new DEROctetString(digest.digest()); - - return new CertID(hashAlg, issuerNameHash, issuerKeyHash, serialNumber); - } - catch (Exception e) - { - throw new OCSPException("problem creating ID: " + e, e); - } - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateStatus.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateStatus.java deleted file mode 100644 index d84b179b5..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/CertificateStatus.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.spongycastle.ocsp; - -public interface CertificateStatus -{ - public static final CertificateStatus GOOD = null; -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPException.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPException.java deleted file mode 100644 index 61516757f..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPException.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.spongycastle.ocsp; - -public class OCSPException - extends Exception -{ - Exception e; - - public OCSPException( - String name) - { - super(name); - } - - public OCSPException( - String name, - Exception e) - { - super(name); - - this.e = e; - } - - public Exception getUnderlyingException() - { - return e; - } - - public Throwable getCause() - { - return e; - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReq.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReq.java deleted file mode 100644 index 6e00fd8db..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReq.java +++ /dev/null @@ -1,417 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertStore; -import java.security.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CollectionCertStoreParameters; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.ocsp.OCSPRequest; -import org.spongycastle.asn1.ocsp.Request; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -/** - *- * OCSPRequest ::= SEQUENCE { - * tbsRequest TBSRequest, - * optionalSignature [0] EXPLICIT Signature OPTIONAL } - * - * TBSRequest ::= SEQUENCE { - * version [0] EXPLICIT Version DEFAULT v1, - * requestorName [1] EXPLICIT GeneralName OPTIONAL, - * requestList SEQUENCE OF Request, - * requestExtensions [2] EXPLICIT Extensions OPTIONAL } - * - * Signature ::= SEQUENCE { - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} - * - * Version ::= INTEGER { v1(0) } - * - * Request ::= SEQUENCE { - * reqCert CertID, - * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } - * - * CertID ::= SEQUENCE { - * hashAlgorithm AlgorithmIdentifier, - * issuerNameHash OCTET STRING, -- Hash of Issuer's DN - * issuerKeyHash OCTET STRING, -- Hash of Issuers public key - * serialNumber CertificateSerialNumber } - *- * - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class OCSPReq - implements java.security.cert.X509Extension -{ - private OCSPRequest req; - - public OCSPReq( - OCSPRequest req) - { - this.req = req; - } - - public OCSPReq( - byte[] req) - throws IOException - { - this(new ASN1InputStream(req)); - } - - public OCSPReq( - InputStream in) - throws IOException - { - this(new ASN1InputStream(in)); - } - - private OCSPReq( - ASN1InputStream aIn) - throws IOException - { - try - { - this.req = OCSPRequest.getInstance(aIn.readObject()); - } - catch (IllegalArgumentException e) - { - throw new IOException("malformed request: " + e.getMessage()); - } - catch (ClassCastException e) - { - throw new IOException("malformed request: " + e.getMessage()); - } - } - - /** - * Return the DER encoding of the tbsRequest field. - * @return DER encoding of tbsRequest - * @throws OCSPException in the event of an encoding error. - */ - public byte[] getTBSRequest() - throws OCSPException - { - try - { - return req.getTbsRequest().getEncoded(); - } - catch (IOException e) - { - throw new OCSPException("problem encoding tbsRequest", e); - } - } - - public int getVersion() - { - return req.getTbsRequest().getVersion().getValue().intValue() + 1; - } - - public GeneralName getRequestorName() - { - return GeneralName.getInstance(req.getTbsRequest().getRequestorName()); - } - - public Req[] getRequestList() - { - ASN1Sequence seq = req.getTbsRequest().getRequestList(); - Req[] requests = new Req[seq.size()]; - - for (int i = 0; i != requests.length; i++) - { - requests[i] = new Req(Request.getInstance(seq.getObjectAt(i))); - } - - return requests; - } - - public X509Extensions getRequestExtensions() - { - return X509Extensions.getInstance(req.getTbsRequest().getRequestExtensions()); - } - - /** - * return the object identifier representing the signature algorithm - */ - public String getSignatureAlgOID() - { - if (!this.isSigned()) - { - return null; - } - - return req.getOptionalSignature().getSignatureAlgorithm().getObjectId().getId(); - } - - public byte[] getSignature() - { - if (!this.isSigned()) - { - return null; - } - - return req.getOptionalSignature().getSignature().getBytes(); - } - - private List getCertList( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = new ArrayList(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - CertificateFactory cf; - - try - { - cf = OCSPUtil.createX509CertificateFactory(provider); - } - catch (CertificateException ex) - { - throw new OCSPException("can't get certificate factory.", ex); - } - - // - // load the certificates if we have any - // - ASN1Sequence s = req.getOptionalSignature().getCerts(); - - if (s != null) - { - Enumeration e = s.getObjects(); - - while (e.hasMoreElements()) - { - try - { - aOut.writeObject((ASN1Encodable)e.nextElement()); - - certs.add(cf.generateCertificate( - new ByteArrayInputStream(bOut.toByteArray()))); - } - catch (IOException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - catch (CertificateException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - - bOut.reset(); - } - } - - return certs; - } - - public X509Certificate[] getCerts( - String provider) - throws OCSPException, NoSuchProviderException - { - if (!this.isSigned()) - { - return null; - } - - List certs = this.getCertList(provider); - - return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); - } - - /** - * If the request is signed return a possibly empty CertStore containing the certificates in the - * request. If the request is not signed the method returns null. - * - * @param type type of CertStore to return - * @param provider provider to use - * @return null if not signed, a CertStore otherwise - * @throws NoSuchAlgorithmException - * @throws NoSuchProviderException - * @throws OCSPException - */ - public CertStore getCertificates( - String type, - String provider) - throws NoSuchAlgorithmException, NoSuchProviderException, OCSPException - { - if (!this.isSigned()) - { - return null; - } - - try - { - CertStoreParameters params = new CollectionCertStoreParameters(this.getCertList(provider)); - return OCSPUtil.createCertStoreInstance(type, params, provider); - } - catch (InvalidAlgorithmParameterException e) - { - throw new OCSPException("can't setup the CertStore", e); - } - } - - /** - * Return whether or not this request is signed. - * - * @return true if signed false otherwise. - */ - public boolean isSigned() - { - return req.getOptionalSignature() != null; - } - - /** - * verify the signature against the TBSRequest object we contain. - */ - public boolean verify( - PublicKey key, - String sigProvider) - throws OCSPException, NoSuchProviderException - { - if (!this.isSigned()) - { - throw new OCSPException("attempt to verify signature on unsigned object"); - } - - try - { - Signature signature = OCSPUtil.createSignatureInstance(this.getSignatureAlgOID(), sigProvider); - - signature.initVerify(key); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(req.getTbsRequest()); - - signature.update(bOut.toByteArray()); - - return signature.verify(this.getSignature()); - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (Exception e) - { - throw new OCSPException("exception processing sig: " + e, e); - } - } - - /** - * return the ASN.1 encoded representation of this object. - */ - public byte[] getEncoded() - throws IOException - { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(req); - - return bOut.toByteArray(); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getRequestExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getRequestExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReqGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReqGenerator.java deleted file mode 100644 index 4e86d24b6..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPReqGenerator.java +++ /dev/null @@ -1,294 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.security.auth.x500.X500Principal; - -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.ocsp.OCSPRequest; -import org.spongycastle.asn1.ocsp.Request; -import org.spongycastle.asn1.ocsp.Signature; -import org.spongycastle.asn1.ocsp.TBSRequest; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.Extensions; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.asn1.x509.X509CertificateStructure; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.jce.X509Principal; - -/** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class OCSPReqGenerator -{ - private List list = new ArrayList(); - private GeneralName requestorName = null; - private X509Extensions requestExtensions = null; - - private class RequestObject - { - CertificateID certId; - X509Extensions extensions; - - public RequestObject( - CertificateID certId, - X509Extensions extensions) - { - this.certId = certId; - this.extensions = extensions; - } - - public Request toRequest() - throws Exception - { - return new Request(certId.toASN1Object(), Extensions.getInstance(extensions)); - } - } - - /** - * Add a request for the given CertificateID. - * - * @param certId certificate ID of interest - */ - public void addRequest( - CertificateID certId) - { - list.add(new RequestObject(certId, null)); - } - - /** - * Add a request with extensions - * - * @param certId certificate ID of interest - * @param singleRequestExtensions the extensions to attach to the request - */ - public void addRequest( - CertificateID certId, - X509Extensions singleRequestExtensions) - { - list.add(new RequestObject(certId, singleRequestExtensions)); - } - - /** - * Set the requestor name to the passed in X500Principal - * - * @param requestorName a X500Principal representing the requestor name. - */ - public void setRequestorName( - X500Principal requestorName) - { - try - { - this.requestorName = new GeneralName(GeneralName.directoryName, new X509Principal(requestorName.getEncoded())); - } - catch (IOException e) - { - throw new IllegalArgumentException("cannot encode principal: " + e); - } - } - - public void setRequestorName( - GeneralName requestorName) - { - this.requestorName = requestorName; - } - - public void setRequestExtensions( - X509Extensions requestExtensions) - { - this.requestExtensions = requestExtensions; - } - - private OCSPReq generateRequest( - DERObjectIdentifier signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException - { - Iterator it = list.iterator(); - - ASN1EncodableVector requests = new ASN1EncodableVector(); - - while (it.hasNext()) - { - try - { - requests.add(((RequestObject)it.next()).toRequest()); - } - catch (Exception e) - { - throw new OCSPException("exception creating Request", e); - } - } - - TBSRequest tbsReq = new TBSRequest(requestorName, new DERSequence(requests), requestExtensions); - - java.security.Signature sig = null; - Signature signature = null; - - if (signingAlgorithm != null) - { - if (requestorName == null) - { - throw new OCSPException("requestorName must be specified if request is signed."); - } - - try - { - sig = OCSPUtil.createSignatureInstance(signingAlgorithm.getId(), provider); - if (random != null) - { - sig.initSign(key, random); - } - else - { - sig.initSign(key); - } - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (GeneralSecurityException e) - { - throw new OCSPException("exception creating signature: " + e, e); - } - - DERBitString bitSig = null; - - try - { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(tbsReq); - - sig.update(bOut.toByteArray()); - - bitSig = new DERBitString(sig.sign()); - } - catch (Exception e) - { - throw new OCSPException("exception processing TBSRequest: " + e, e); - } - - AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, DERNull.INSTANCE); - - if (chain != null && chain.length > 0) - { - ASN1EncodableVector v = new ASN1EncodableVector(); - try - { - for (int i = 0; i != chain.length; i++) - { - v.add(new X509CertificateStructure( - (ASN1Sequence)ASN1Primitive.fromByteArray(chain[i].getEncoded()))); - } - } - catch (IOException e) - { - throw new OCSPException("error processing certs", e); - } - catch (CertificateEncodingException e) - { - throw new OCSPException("error encoding certs", e); - } - - signature = new Signature(sigAlgId, bitSig, new DERSequence(v)); - } - else - { - signature = new Signature(sigAlgId, bitSig); - } - } - - return new OCSPReq(new OCSPRequest(tbsReq, signature)); - } - - /** - * Generate an unsigned request - * - * @return the OCSPReq - * @throws OCSPException - */ - public OCSPReq generate() - throws OCSPException - { - try - { - return generateRequest(null, null, null, null, null); - } - catch (NoSuchProviderException e) - { - // - // this shouldn't happen but... - // - throw new OCSPException("no provider! - " + e, e); - } - } - - public OCSPReq generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - return generate(signingAlgorithm, key, chain, provider, null); - } - - public OCSPReq generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - if (signingAlgorithm == null) - { - throw new IllegalArgumentException("no signing algorithm specified"); - } - - try - { - DERObjectIdentifier oid = OCSPUtil.getAlgorithmOID(signingAlgorithm); - - return generateRequest(oid, key, chain, provider, random); - } - catch (IllegalArgumentException e) - { - throw new IllegalArgumentException("unknown signing algorithm specified: " + signingAlgorithm); - } - } - - /** - * Return an iterator of the signature names supported by the generator. - * - * @return an iterator containing recognised names. - */ - public Iterator getSignatureAlgNames() - { - return OCSPUtil.getAlgNames(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPResp.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPResp.java deleted file mode 100644 index fccd7d156..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPResp.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.IOException; -import java.io.InputStream; - -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ocsp.BasicOCSPResponse; -import org.spongycastle.asn1.ocsp.OCSPObjectIdentifiers; -import org.spongycastle.asn1.ocsp.OCSPResponse; -import org.spongycastle.asn1.ocsp.ResponseBytes; - -/** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class OCSPResp -{ - private OCSPResponse resp; - - /** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ - public OCSPResp( - OCSPResponse resp) - { - this.resp = resp; - } - - /** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ - public OCSPResp( - byte[] resp) - throws IOException - { - this(new ASN1InputStream(resp)); - } - - /** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ - public OCSPResp( - InputStream in) - throws IOException - { - this(new ASN1InputStream(in)); - } - - private OCSPResp( - ASN1InputStream aIn) - throws IOException - { - try - { - this.resp = OCSPResponse.getInstance(aIn.readObject()); - } - catch (IllegalArgumentException e) - { - throw new IOException("malformed response: " + e.getMessage()); - } - catch (ClassCastException e) - { - throw new IOException("malformed response: " + e.getMessage()); - } - } - - public int getStatus() - { - return this.resp.getResponseStatus().getValue().intValue(); - } - - public Object getResponseObject() - throws OCSPException - { - ResponseBytes rb = this.resp.getResponseBytes(); - - if (rb == null) - { - return null; - } - - if (rb.getResponseType().equals(OCSPObjectIdentifiers.id_pkix_ocsp_basic)) - { - try - { - ASN1Primitive obj = ASN1Primitive.fromByteArray(rb.getResponse().getOctets()); - return new BasicOCSPResp(BasicOCSPResponse.getInstance(obj)); - } - catch (Exception e) - { - throw new OCSPException("problem decoding object: " + e, e); - } - } - - return rb.getResponse(); - } - - /** - * return the ASN.1 encoded representation of this object. - */ - public byte[] getEncoded() - throws IOException - { - return resp.getEncoded(); - } - - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - - if (!(o instanceof OCSPResp)) - { - return false; - } - - OCSPResp r = (OCSPResp)o; - - return resp.equals(r.resp); - } - - public int hashCode() - { - return resp.hashCode(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespGenerator.java deleted file mode 100644 index 791705d12..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespGenerator.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.IOException; - -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.ocsp.OCSPObjectIdentifiers; -import org.spongycastle.asn1.ocsp.OCSPResponse; -import org.spongycastle.asn1.ocsp.OCSPResponseStatus; -import org.spongycastle.asn1.ocsp.ResponseBytes; - -/** - * base generator for an OCSP response - at the moment this only supports the - * generation of responses containing BasicOCSP responses. - * - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class OCSPRespGenerator -{ - public static final int SUCCESSFUL = 0; // Response has valid confirmations - public static final int MALFORMED_REQUEST = 1; // Illegal confirmation request - public static final int INTERNAL_ERROR = 2; // Internal error in issuer - public static final int TRY_LATER = 3; // Try again later - // (4) is not used - public static final int SIG_REQUIRED = 5; // Must sign the request - public static final int UNAUTHORIZED = 6; // Request unauthorized - - public OCSPResp generate( - int status, - Object response) - throws OCSPException - { - if (response == null) - { - return new OCSPResp(new OCSPResponse(new OCSPResponseStatus(status),null)); - } - if (response instanceof BasicOCSPResp) - { - BasicOCSPResp r = (BasicOCSPResp)response; - ASN1OctetString octs; - - try - { - octs = new DEROctetString(r.getEncoded()); - } - catch (IOException e) - { - throw new OCSPException("can't encode object.", e); - } - - ResponseBytes rb = new ResponseBytes( - OCSPObjectIdentifiers.id_pkix_ocsp_basic, octs); - - return new OCSPResp(new OCSPResponse( - new OCSPResponseStatus(status), rb)); - } - - throw new OCSPException("unknown response object"); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespStatus.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespStatus.java deleted file mode 100644 index dde33ce8a..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPRespStatus.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.spongycastle.ocsp; - -public interface OCSPRespStatus -{ - /** - * note 4 is not used. - */ - public static final int SUCCESSFUL = 0; // --Response has valid confirmations - public static final int MALFORMED_REQUEST = 1; // --Illegal confirmation request - public static final int INTERNAL_ERROR = 2; // --Internal error in issuer - public static final int TRY_LATER = 3; // --Try again later - public static final int SIGREQUIRED = 5; // --Must sign the request - public static final int UNAUTHORIZED = 6; // --Request unauthorized -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPUtil.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPUtil.java deleted file mode 100644 index 1d4ba6cf3..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/OCSPUtil.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.spongycastle.ocsp; - -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; -import org.spongycastle.asn1.nist.NISTObjectIdentifiers; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x9.X9ObjectIdentifiers; -import org.spongycastle.util.Strings; - -import java.security.InvalidAlgorithmParameterException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Signature; -import java.security.cert.CertStore; -import java.security.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -class OCSPUtil -{ - private static Hashtable algorithms = new Hashtable(); - private static Hashtable oids = new Hashtable(); - private static Set noParams = new HashSet(); - - static - { - algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); - algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); - algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); - algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); - algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); - algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); - algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - - oids.put(PKCSObjectIdentifiers.md2WithRSAEncryption, "MD2WITHRSA"); - oids.put(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160, "RIPEMD160WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128, "RIPEMD128WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256, "RIPEMD256WITHRSA"); - oids.put(X9ObjectIdentifiers.id_dsa_with_sha1, "SHA1WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha224, "SHA224WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha256, "SHA256WITHDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512WITHECDSA"); - oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); - - // - // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. - // The parameters field SHALL be NULL for RSA based signature algorithms. - // - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); - noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); - noParams.add(NISTObjectIdentifiers.dsa_with_sha224); - noParams.add(NISTObjectIdentifiers.dsa_with_sha256); - } - - static DERObjectIdentifier getAlgorithmOID( - String algorithmName) - { - algorithmName = Strings.toUpperCase(algorithmName); - - if (algorithms.containsKey(algorithmName)) - { - return (DERObjectIdentifier)algorithms.get(algorithmName); - } - - return new DERObjectIdentifier(algorithmName); - } - - static String getAlgorithmName( - DERObjectIdentifier oid) - { - if (oids.containsKey(oid)) - { - return (String)oids.get(oid); - } - - return oid.getId(); - } - - static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid) - { - if (noParams.contains(sigOid)) - { - return new AlgorithmIdentifier(sigOid); - } - else - { - return new AlgorithmIdentifier(sigOid, DERNull.INSTANCE); - } - } - - static Iterator getAlgNames() - { - Enumeration e = algorithms.keys(); - List l = new ArrayList(); - - while (e.hasMoreElements()) - { - l.add(e.nextElement()); - } - - return l.iterator(); - } - - static CertStore createCertStoreInstance(String type, CertStoreParameters params, String provider) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return CertStore.getInstance(type, params); - } - - return CertStore.getInstance(type, params, provider); - } - - static MessageDigest createDigestInstance(String digestName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return MessageDigest.getInstance(digestName); - } - - return MessageDigest.getInstance(digestName, provider); - } - - static Signature createSignatureInstance(String sigName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return Signature.getInstance(sigName); - } - - return Signature.getInstance(sigName, provider); - } - - static CertificateFactory createX509CertificateFactory(String provider) - throws CertificateException, NoSuchProviderException - { - if (provider == null) - { - return CertificateFactory.getInstance("X.509"); - } - - return CertificateFactory.getInstance("X.509", provider); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/Req.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/Req.java deleted file mode 100644 index 7f67a5622..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/Req.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.spongycastle.ocsp; - -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.ocsp.Request; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -public class Req - implements java.security.cert.X509Extension -{ - private Request req; - - public Req( - Request req) - { - this.req = req; - } - - public CertificateID getCertID() - { - return new CertificateID(req.getReqCert()); - } - - public X509Extensions getSingleRequestExtensions() - { - return X509Extensions.getInstance(req.getSingleRequestExtensions()); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getSingleRequestExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getSingleRequestExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespData.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespData.java deleted file mode 100644 index 10095546d..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespData.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.spongycastle.ocsp; - -import java.text.ParseException; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.ocsp.ResponseData; -import org.spongycastle.asn1.ocsp.SingleResponse; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -public class RespData - implements java.security.cert.X509Extension -{ - ResponseData data; - - public RespData( - ResponseData data) - { - this.data = data; - } - - public int getVersion() - { - return data.getVersion().getValue().intValue() + 1; - } - - public RespID getResponderId() - { - return new RespID(data.getResponderID()); - } - - public Date getProducedAt() - { - try - { - return data.getProducedAt().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException:" + e.getMessage()); - } - } - - public SingleResp[] getResponses() - { - ASN1Sequence s = data.getResponses(); - SingleResp[] rs = new SingleResp[s.size()]; - - for (int i = 0; i != rs.length; i++) - { - rs[i] = new SingleResp(SingleResponse.getInstance(s.getObjectAt(i))); - } - - return rs; - } - - public X509Extensions getResponseExtensions() - { - return X509Extensions.getInstance(data.getResponseExtensions()); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getResponseExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getResponseExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespID.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespID.java deleted file mode 100644 index 18c471886..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RespID.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.spongycastle.ocsp; - -import java.security.MessageDigest; -import java.security.PublicKey; - -import javax.security.auth.x500.X500Principal; - -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.ocsp.ResponderID; -import org.spongycastle.asn1.x500.X500Name; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; - -/** - * Carrier for a ResponderID. - */ -public class RespID -{ - ResponderID id; - - public RespID( - ResponderID id) - { - this.id = id; - } - - public RespID( - X500Principal name) - { - this.id = new ResponderID(X500Name.getInstance(name.getEncoded())); - } - - public RespID( - PublicKey key) - throws OCSPException - { - try - { - // TODO Allow specification of a particular provider - MessageDigest digest = OCSPUtil.createDigestInstance("SHA1", null); - - ASN1InputStream aIn = new ASN1InputStream(key.getEncoded()); - SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject()); - - digest.update(info.getPublicKeyData().getBytes()); - - ASN1OctetString keyHash = new DEROctetString(digest.digest()); - - this.id = new ResponderID(keyHash); - } - catch (Exception e) - { - throw new OCSPException("problem creating ID: " + e, e); - } - } - - public ResponderID toASN1Object() - { - return id; - } - - public boolean equals( - Object o) - { - if (!(o instanceof RespID)) - { - return false; - } - - RespID obj = (RespID)o; - - return id.equals(obj.id); - } - - public int hashCode() - { - return id.hashCode(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RevokedStatus.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RevokedStatus.java deleted file mode 100644 index 4643d53b1..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/RevokedStatus.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.spongycastle.ocsp; - -import java.text.ParseException; -import java.util.Date; - -import org.spongycastle.asn1.ASN1GeneralizedTime; -import org.spongycastle.asn1.ocsp.RevokedInfo; -import org.spongycastle.asn1.x509.CRLReason; - -/** - * wrapper for the RevokedInfo object - */ -public class RevokedStatus - implements CertificateStatus -{ - RevokedInfo info; - - public RevokedStatus( - RevokedInfo info) - { - this.info = info; - } - - public RevokedStatus( - Date revocationDate, - int reason) - { - this.info = new RevokedInfo(new ASN1GeneralizedTime(revocationDate), CRLReason.lookup(reason)); - } - - public Date getRevocationTime() - { - try - { - return info.getRevocationTime().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException:" + e.getMessage()); - } - } - - public boolean hasRevocationReason() - { - return (info.getRevocationReason() != null); - } - - /** - * return the revocation reason. Note: this field is optional, test for it - * with hasRevocationReason() first. - * @return the revocation reason value. - * @exception IllegalStateException if a reason is asked for and none is avaliable - */ - public int getRevocationReason() - { - if (info.getRevocationReason() == null) - { - throw new IllegalStateException("attempt to get a reason where none is available"); - } - - return info.getRevocationReason().getValue().intValue(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/SingleResp.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/SingleResp.java deleted file mode 100644 index ead05d93a..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/SingleResp.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.spongycastle.ocsp; - -import java.text.ParseException; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.ocsp.CertStatus; -import org.spongycastle.asn1.ocsp.RevokedInfo; -import org.spongycastle.asn1.ocsp.SingleResponse; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -public class SingleResp - implements java.security.cert.X509Extension -{ - SingleResponse resp; - - public SingleResp( - SingleResponse resp) - { - this.resp = resp; - } - - public CertificateID getCertID() - { - return new CertificateID(resp.getCertID()); - } - - /** - * Return the status object for the response - null indicates good. - * - * @return the status object for the response, null if it is good. - */ - public Object getCertStatus() - { - CertStatus s = resp.getCertStatus(); - - if (s.getTagNo() == 0) - { - return null; // good - } - else if (s.getTagNo() == 1) - { - return new RevokedStatus(RevokedInfo.getInstance(s.getStatus())); - } - - return new UnknownStatus(); - } - - public Date getThisUpdate() - { - try - { - return resp.getThisUpdate().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException: " + e.getMessage()); - } - } - - /** - * return the NextUpdate value - note: this is an optional field so may - * be returned as null. - * - * @return nextUpdate, or null if not present. - */ - public Date getNextUpdate() - { - if (resp.getNextUpdate() == null) - { - return null; - } - - try - { - return resp.getNextUpdate().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException: " + e.getMessage()); - } - } - - public X509Extensions getSingleExtensions() - { - return X509Extensions.getInstance(resp.getSingleExtensions()); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - - return extns != null && !extns.isEmpty(); - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getSingleExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getSingleExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/UnknownStatus.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/UnknownStatus.java deleted file mode 100644 index d8b503970..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/ocsp/UnknownStatus.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.spongycastle.ocsp; - -/** - * wrapper for the UnknownInfo object - */ -public class UnknownStatus - implements CertificateStatus -{ - public UnknownStatus() - { - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/PKIXCertPathReviewer.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/PKIXCertPathReviewer.java index 6f8ed6aaf..5e4444409 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/PKIXCertPathReviewer.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/PKIXCertPathReviewer.java @@ -37,15 +37,15 @@ import java.util.Vector; import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1Enumerated; import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DEREnumerated; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.x509.AccessDescription; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -809,7 +809,7 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities X509Certificate sign = null; AlgorithmIdentifier workingAlgId = null; - DERObjectIdentifier workingPublicKeyAlgorithm = null; + ASN1ObjectIdentifier workingPublicKeyAlgorithm = null; ASN1Encodable workingPublicKeyParameters = null; if (trust != null) @@ -1215,7 +1215,7 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities while (e.hasMoreElements()) { PolicyInformation pInfo = PolicyInformation.getInstance(e.nextElement()); - DERObjectIdentifier pOid = pInfo.getPolicyIdentifier(); + ASN1ObjectIdentifier pOid = pInfo.getPolicyIdentifier(); pols.add(pOid.getId()); @@ -1301,9 +1301,9 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities { _policy = (String) _tmp; } - else if (_tmp instanceof DERObjectIdentifier) + else if (_tmp instanceof ASN1ObjectIdentifier) { - _policy = ((DERObjectIdentifier) _tmp).getId(); + _policy = ((ASN1ObjectIdentifier) _tmp).getId(); } else { @@ -1425,8 +1425,8 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities for (int j = 0; j < mappings.size(); j++) { ASN1Sequence mapping = (ASN1Sequence) mappings.getObjectAt(j); - DERObjectIdentifier ip_id = (DERObjectIdentifier) mapping.getObjectAt(0); - DERObjectIdentifier sp_id = (DERObjectIdentifier) mapping.getObjectAt(1); + ASN1ObjectIdentifier ip_id = (ASN1ObjectIdentifier) mapping.getObjectAt(0); + ASN1ObjectIdentifier sp_id = (ASN1ObjectIdentifier) mapping.getObjectAt(1); if (ANY_POLICY.equals(ip_id.getId())) { ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.invalidPolicyMapping"); @@ -1451,8 +1451,8 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities for (int j = 0; j < mappings.size(); j++) { ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j); - String id_p = ((DERObjectIdentifier)mapping.getObjectAt(0)).getId(); - String sd_p = ((DERObjectIdentifier)mapping.getObjectAt(1)).getId(); + String id_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(0)).getId(); + String sd_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(1)).getId(); Set tmp; if (!m_idp.containsKey(id_p)) @@ -1554,14 +1554,14 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities switch (constraint.getTagNo()) { case 0: - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < explicitPolicy) { explicitPolicy = tmpInt; } break; case 1: - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < policyMapping) { policyMapping = tmpInt; @@ -1583,7 +1583,7 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities try { - DERInteger iap = (DERInteger)getExtensionValue(cert, INHIBIT_ANY_POLICY); + ASN1Integer iap = (ASN1Integer)getExtensionValue(cert, INHIBIT_ANY_POLICY); if (iap != null) { @@ -1634,7 +1634,7 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities switch (constraint.getTagNo()) { case 0: - int tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + int tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt == 0) { explicitPolicy = 0; @@ -1906,7 +1906,7 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities while (it.hasNext()) { msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.unknownCriticalExt", - new Object[] {new DERObjectIdentifier((String) it.next())}); + new Object[] {new ASN1ObjectIdentifier((String) it.next())}); addError(msg, index); } } @@ -2206,10 +2206,10 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities if (crl_entry.hasExtensions()) { - DEREnumerated reasonCode; + ASN1Enumerated reasonCode; try { - reasonCode = DEREnumerated.getInstance(getExtensionValue(crl_entry, X509Extensions.ReasonCode.getId())); + reasonCode = ASN1Enumerated.getInstance(getExtensionValue(crl_entry, X509Extensions.ReasonCode.getId())); } catch (AnnotatedException ae) { @@ -2297,10 +2297,10 @@ public class PKIXCertPathReviewer extends CertPathValidatorUtilities throw new CertPathReviewerException(msg,e); } - baseSelect.setMinCRLNumber(((DERInteger)dci).getPositiveValue()); + baseSelect.setMinCRLNumber(((ASN1Integer)dci).getPositiveValue()); try { - baseSelect.setMaxCRLNumber(((DERInteger)getExtensionValue(crl, CRL_NUMBER)).getPositiveValue().subtract(BigInteger.valueOf(1))); + baseSelect.setMaxCRLNumber(((ASN1Integer)getExtensionValue(crl, CRL_NUMBER)).getPositiveValue().subtract(BigInteger.valueOf(1))); } catch (AnnotatedException ae) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509AttributeCertificate.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509AttributeCertificate.java index e0f663c2e..bad472253 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509AttributeCertificate.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509AttributeCertificate.java @@ -15,6 +15,7 @@ import java.util.Date; /** * Interface for an X.509 Attribute Certificate. + * @deprecated use X509CertificateHolder class in the PKIX package. */ public interface X509AttributeCertificate extends X509Extension diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CRLStoreSelector.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CRLStoreSelector.java index 8572afa53..1e849a344 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CRLStoreSelector.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CRLStoreSelector.java @@ -1,17 +1,17 @@ package org.spongycastle.x509; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.util.Arrays; -import org.spongycastle.util.Selector; -import org.spongycastle.x509.extension.X509ExtensionUtil; - import java.io.IOException; import java.math.BigInteger; import java.security.cert.CRL; import java.security.cert.X509CRL; import java.security.cert.X509CRLSelector; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Selector; +import org.spongycastle.x509.extension.X509ExtensionUtil; + /** * This class is a Selector implementation for X.509 certificate revocation * lists. @@ -96,14 +96,14 @@ public class X509CRLStoreSelector return false; } X509CRL crl = (X509CRL)obj; - DERInteger dci = null; + ASN1Integer dci = null; try { byte[] bytes = crl .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); if (bytes != null) { - dci = DERInteger.getInstance(X509ExtensionUtil + dci = ASN1Integer.getInstance(X509ExtensionUtil .fromExtensionValue(bytes)); } } diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CertStoreSelector.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CertStoreSelector.java index 80ea1c3ab..d78e57f19 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CertStoreSelector.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509CertStoreSelector.java @@ -1,18 +1,19 @@ package org.spongycastle.x509; -import org.spongycastle.util.Selector; - import java.io.IOException; import java.security.cert.Certificate; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; +import org.spongycastle.util.Selector; + /** * This class is a Selector implementation for X.509 certificates. * * @see org.spongycastle.util.Selector * @see org.spongycastle.x509.X509Store * @see org.spongycastle.jce.provider.X509StoreCertCollection + * @deprecated use the classes under org.spongycastle.cert.selector */ public class X509CertStoreSelector extends X509CertSelector diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509Util.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509Util.java index 0bfd71e05..c734942dd 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509Util.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509Util.java @@ -23,8 +23,8 @@ import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -136,21 +136,21 @@ class X509Util new ASN1Integer(1)); } - static DERObjectIdentifier getAlgorithmOID( + static ASN1ObjectIdentifier getAlgorithmOID( String algorithmName) { algorithmName = Strings.toUpperCase(algorithmName); if (algorithms.containsKey(algorithmName)) { - return (DERObjectIdentifier)algorithms.get(algorithmName); + return (ASN1ObjectIdentifier)algorithms.get(algorithmName); } - return new DERObjectIdentifier(algorithmName); + return new ASN1ObjectIdentifier(algorithmName); } static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String algorithmName) { if (noParams.contains(sigOid)) @@ -206,7 +206,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, PrivateKey key, SecureRandom random, @@ -237,7 +237,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, String provider, PrivateKey key, diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V1CertificateGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V1CertificateGenerator.java index 5d9920c32..398d77f4a 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V1CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V1CertificateGenerator.java @@ -22,9 +22,9 @@ import javax.security.auth.x500.X500Principal; import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.Certificate; @@ -43,7 +43,7 @@ import org.spongycastle.jce.provider.X509CertificateObject; public class X509V1CertificateGenerator { private V1TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java deleted file mode 100644 index ee3aeed84..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java +++ /dev/null @@ -1,269 +0,0 @@ -package org.spongycastle.x509; - -import java.io.IOException; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.SignatureException; -import java.security.cert.CertificateEncodingException; -import java.util.Date; -import java.util.Iterator; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1GeneralizedTime; -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.AttCertIssuer; -import org.spongycastle.asn1.x509.Attribute; -import org.spongycastle.asn1.x509.AttributeCertificate; -import org.spongycastle.asn1.x509.AttributeCertificateInfo; -import org.spongycastle.asn1.x509.V2AttributeCertificateInfoGenerator; -import org.spongycastle.asn1.x509.X509ExtensionsGenerator; - -/** - * class to produce an X.509 Version 2 AttributeCertificate. - * @deprecated use org.spongycastle.cert.X509v2AttributeCertificateBuilder - */ -public class X509V2AttributeCertificateGenerator -{ - private V2AttributeCertificateInfoGenerator acInfoGen; - private DERObjectIdentifier sigOID; - private AlgorithmIdentifier sigAlgId; - private String signatureAlgorithm; - private X509ExtensionsGenerator extGenerator; - - public X509V2AttributeCertificateGenerator() - { - acInfoGen = new V2AttributeCertificateInfoGenerator(); - extGenerator = new X509ExtensionsGenerator(); - } - - /** - * reset the generator - */ - public void reset() - { - acInfoGen = new V2AttributeCertificateInfoGenerator(); - extGenerator.reset(); - } - - /** - * Set the Holder of this Attribute Certificate - */ - public void setHolder( - AttributeCertificateHolder holder) - { - acInfoGen.setHolder(holder.holder); - } - - /** - * Set the issuer - */ - public void setIssuer( - AttributeCertificateIssuer issuer) - { - acInfoGen.setIssuer(AttCertIssuer.getInstance(issuer.form)); - } - - /** - * set the serial number for the certificate. - */ - public void setSerialNumber( - BigInteger serialNumber) - { - acInfoGen.setSerialNumber(new ASN1Integer(serialNumber)); - } - - public void setNotBefore( - Date date) - { - acInfoGen.setStartDate(new ASN1GeneralizedTime(date)); - } - - public void setNotAfter( - Date date) - { - acInfoGen.setEndDate(new ASN1GeneralizedTime(date)); - } - - /** - * Set the signature algorithm. This can be either a name or an OID, names - * are treated as case insensitive. - * - * @param signatureAlgorithm string representation of the algorithm name. - */ - public void setSignatureAlgorithm( - String signatureAlgorithm) - { - this.signatureAlgorithm = signatureAlgorithm; - - try - { - sigOID = X509Util.getAlgorithmOID(signatureAlgorithm); - } - catch (Exception e) - { - throw new IllegalArgumentException("Unknown signature type requested"); - } - - sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm); - - acInfoGen.setSignature(sigAlgId); - } - - /** - * add an attribute - */ - public void addAttribute( - X509Attribute attribute) - { - acInfoGen.addAttribute(Attribute.getInstance(attribute.toASN1Object())); - } - - public void setIssuerUniqueId( - boolean[] iui) - { - // [TODO] convert boolean array to bit string - //acInfoGen.setIssuerUniqueID(iui); - throw new RuntimeException("not implemented (yet)"); - } - - /** - * add a given extension field for the standard extensions tag - * @throws IOException - */ - public void addExtension( - String oid, - boolean critical, - ASN1Encodable value) - throws IOException - { - extGenerator.addExtension(new ASN1ObjectIdentifier(oid), critical, value); - } - - /** - * add a given extension field for the standard extensions tag - * The value parameter becomes the contents of the octet string associated - * with the extension. - */ - public void addExtension( - String oid, - boolean critical, - byte[] value) - { - extGenerator.addExtension(new ASN1ObjectIdentifier(oid), critical, value); - } - - /** - * generate an X509 certificate, based on the current issuer and subject, - * using the passed in provider for the signing. - * @deprecated use generate() - */ - public X509AttributeCertificate generateCertificate( - PrivateKey key, - String provider) - throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException - { - return generateCertificate(key, provider, null); - } - - /** - * generate an X509 certificate, based on the current issuer and subject, - * using the passed in provider for the signing and the supplied source - * of randomness, if required. - * @deprecated use generate() - */ - public X509AttributeCertificate generateCertificate( - PrivateKey key, - String provider, - SecureRandom random) - throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException - { - try - { - return generate(key, provider, random); - } - catch (NoSuchProviderException e) - { - throw e; - } - catch (SignatureException e) - { - throw e; - } - catch (InvalidKeyException e) - { - throw e; - } - catch (GeneralSecurityException e) - { - throw new SecurityException("exception creating certificate: " + e); - } - } - - /** - * generate an X509 certificate, based on the current issuer and subject, - * using the passed in provider for the signing. - */ - public X509AttributeCertificate generate( - PrivateKey key, - String provider) - throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, SignatureException, InvalidKeyException, NoSuchAlgorithmException - { - return generate(key, provider, null); - } - - /** - * generate an X509 certificate, based on the current issuer and subject, - * using the passed in provider for the signing and the supplied source - * of randomness, if required. - */ - public X509AttributeCertificate generate( - PrivateKey key, - String provider, - SecureRandom random) - throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException - { - if (!extGenerator.isEmpty()) - { - acInfoGen.setExtensions(extGenerator.generate()); - } - - AttributeCertificateInfo acInfo = acInfoGen.generateAttributeCertificateInfo(); - - ASN1EncodableVector v = new ASN1EncodableVector(); - - v.add(acInfo); - v.add(sigAlgId); - - try - { - v.add(new DERBitString(X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, acInfo))); - - return new X509V2AttributeCertificate(new AttributeCertificate(new DERSequence(v))); - } - catch (IOException e) - { - throw new ExtCertificateEncodingException("constructed invalid certificate", e); - } - } - - /** - * Return an iterator of the signature names supported by the generator. - * - * @return an iterator containing recognised names. - */ - public Iterator getSignatureAlgNames() - { - return X509Util.getAlgNames(); - } -} diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2CRLGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2CRLGenerator.java index 4da0b8e09..457883e63 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2CRLGenerator.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V2CRLGenerator.java @@ -26,7 +26,6 @@ import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.CertificateList; @@ -47,7 +46,7 @@ import org.spongycastle.jce.provider.X509CRLObject; public class X509V2CRLGenerator { private V2TBSCertListGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -197,14 +196,14 @@ public class X509V2CRLGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -219,14 +218,14 @@ public class X509V2CRLGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V3CertificateGenerator.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V3CertificateGenerator.java index 7ec1455b4..5f5cae941 100644 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V3CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/X509V3CertificateGenerator.java @@ -24,7 +24,6 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.Certificate; @@ -45,7 +44,7 @@ import org.spongycastle.x509.extension.X509ExtensionUtil; public class X509V3CertificateGenerator { private V3TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -228,14 +227,14 @@ public class X509V3CertificateGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -252,14 +251,14 @@ public class X509V3CertificateGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { @@ -302,7 +301,7 @@ public class X509V3CertificateGenerator * @throws CertificateParsingException if the extension cannot be extracted. */ public void copyAndAddExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, X509Certificate cert) throws CertificateParsingException diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/examples/AttrCertExample.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/examples/AttrCertExample.java deleted file mode 100644 index 28f065cef..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/examples/AttrCertExample.java +++ /dev/null @@ -1,314 +0,0 @@ -package org.spongycastle.x509.examples; - -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Security; -import java.security.cert.X509Certificate; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.util.Date; -import java.util.Hashtable; -import java.util.Vector; - -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.misc.MiscObjectIdentifiers; -import org.spongycastle.asn1.misc.NetscapeCertType; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.jce.X509Principal; -import org.spongycastle.jce.provider.BouncyCastleProvider; -import org.spongycastle.x509.AttributeCertificateHolder; -import org.spongycastle.x509.AttributeCertificateIssuer; -import org.spongycastle.x509.X509Attribute; -import org.spongycastle.x509.X509V1CertificateGenerator; -import org.spongycastle.x509.X509V2AttributeCertificate; -import org.spongycastle.x509.X509V2AttributeCertificateGenerator; -import org.spongycastle.x509.X509V3CertificateGenerator; - -/** - * A simple example that generates an attribute certificate. - */ -public class AttrCertExample -{ - static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator(); - static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); - - /** - * we generate the AC issuer's certificate - */ - public static X509Certificate createAcIssuerCert( - PublicKey pubKey, - PrivateKey privKey) - throws Exception - { - // - // signers name - // - String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // subjects name - the same as we are self signed. - // - String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // create the certificate - version 1 - // - - v1CertGen.setSerialNumber(BigInteger.valueOf(10)); - v1CertGen.setIssuerDN(new X509Principal(issuer)); - v1CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v1CertGen.setSubjectDN(new X509Principal(subject)); - v1CertGen.setPublicKey(pubKey); - v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - X509Certificate cert = v1CertGen.generate(privKey); - - cert.checkValidity(new Date()); - - cert.verify(pubKey); - - return cert; - } - - /** - * we generate a certificate signed by our CA's intermediate certficate - */ - public static X509Certificate createClientCert( - PublicKey pubKey, - PrivateKey caPrivKey, - PublicKey caPubKey) - throws Exception - { - // - // issuer - // - String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // subjects name table. - // - Hashtable attrs = new Hashtable(); - Vector order = new Vector(); - - attrs.put(X509Principal.C, "AU"); - attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); - attrs.put(X509Principal.L, "Melbourne"); - attrs.put(X509Principal.CN, "Eric H. Echidna"); - attrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); - - order.addElement(X509Principal.C); - order.addElement(X509Principal.O); - order.addElement(X509Principal.L); - order.addElement(X509Principal.CN); - order.addElement(X509Principal.EmailAddress); - - // - // create the certificate - version 3 - // - v3CertGen.reset(); - - v3CertGen.setSerialNumber(BigInteger.valueOf(20)); - v3CertGen.setIssuerDN(new X509Principal(issuer)); - v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v3CertGen.setSubjectDN(new X509Principal(order, attrs)); - v3CertGen.setPublicKey(pubKey); - v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // - // add the extensions - // - - v3CertGen.addExtension( - MiscObjectIdentifiers.netscapeCertType, - false, - new NetscapeCertType(NetscapeCertType.objectSigning | NetscapeCertType.smime)); - - X509Certificate cert = v3CertGen.generate(caPrivKey); - - cert.checkValidity(new Date()); - - cert.verify(caPubKey); - - return cert; - } - - public static void main(String args[]) - throws Exception - { - Security.addProvider(new BouncyCastleProvider()); - - // - // personal keys - // - RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16), - new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), - new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), - new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), - new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), - new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), - new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); - - // - // ca keys - // - RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16), - new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16), - new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16), - new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16), - new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16), - new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16), - new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16)); - - // - // set up the keys - // - KeyFactory fact = KeyFactory.getInstance("RSA", "SC"); - PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec); - PublicKey caPubKey = fact.generatePublic(caPubKeySpec); - PrivateKey privKey = fact.generatePrivate(privKeySpec); - PublicKey pubKey = fact.generatePublic(pubKeySpec); - - // - // note in this case we are using the CA certificate for both the client cetificate - // and the attribute certificate. This is to make the vcode simpler to read, in practice - // the CA for the attribute certificate should be different to that of the client certificate - // - X509Certificate caCert = createAcIssuerCert(caPubKey, caPrivKey); - X509Certificate clientCert = createClientCert(pubKey, caPrivKey, caPubKey); - - // Instantiate a new AC generator - X509V2AttributeCertificateGenerator acGen = new X509V2AttributeCertificateGenerator(); - - acGen.reset(); - - // - // Holder: here we use the IssuerSerial form - // - acGen.setHolder(new AttributeCertificateHolder(clientCert)); - - // set the Issuer - acGen.setIssuer(new AttributeCertificateIssuer(caCert.getSubjectX500Principal())); - - // - // serial number (as it's an example we don't have to keep track of the - // serials anyway - // - acGen.setSerialNumber(new BigInteger("1")); - - // not Before - acGen.setNotBefore(new Date(System.currentTimeMillis() - 50000)); - - // not After - acGen.setNotAfter(new Date(System.currentTimeMillis() + 50000)); - - // signature Algorithmus - acGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // the actual attributes - GeneralName roleName = new GeneralName(GeneralName.rfc822Name, "DAU123456789"); - ASN1EncodableVector roleSyntax = new ASN1EncodableVector(); - roleSyntax.add(roleName); - - // roleSyntax OID: 2.5.24.72 - X509Attribute attributes = new X509Attribute("2.5.24.72", - new DERSequence(roleSyntax)); - - acGen.addAttribute(attributes); - - // finally create the AC - X509V2AttributeCertificate att = (X509V2AttributeCertificate)acGen - .generate(caPrivKey, "SC"); - - // - // starting here, we parse the newly generated AC - // - - // Holder - - AttributeCertificateHolder h = att.getHolder(); - if (h.match(clientCert)) - { - if (h.getEntityNames() != null) - { - System.out.println(h.getEntityNames().length + " entity names found"); - } - if (h.getIssuer() != null) - { - System.out.println(h.getIssuer().length + " issuer names found, serial number " + h.getSerialNumber()); - } - System.out.println("Matches original client x509 cert"); - } - - // Issuer - - AttributeCertificateIssuer issuer = att.getIssuer(); - if (issuer.match(caCert)) - { - if (issuer.getPrincipals() != null) - { - System.out.println(issuer.getPrincipals().length + " entity names found"); - } - System.out.println("Matches original ca x509 cert"); - } - - // Dates - System.out.println("valid not before: " + att.getNotBefore()); - System.out.println("valid not before: " + att.getNotAfter()); - - // check the dates, an exception is thrown in checkValidity()... - - try - { - att.checkValidity(); - att.checkValidity(new Date()); - } - catch (Exception e) - { - System.out.println(e); - } - - // verify - - try - { - att.verify(caPubKey, "SC"); - } - catch (Exception e) - { - System.out.println(e); - } - - // Attribute - X509Attribute[] attribs = att.getAttributes(); - System.out.println("cert has " + attribs.length + " attributes:"); - for (int i = 0; i < attribs.length; i++) - { - X509Attribute a = attribs[i]; - System.out.println("OID: " + a.getOID()); - - // currently we only check for the presence of a 'RoleSyntax' attribute - - if (a.getOID().equals("2.5.24.72")) - { - System.out.println("rolesyntax read from cert!"); - } - } - } -} \ No newline at end of file diff --git a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/extension/SubjectKeyIdentifierStructure.java b/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/extension/SubjectKeyIdentifierStructure.java deleted file mode 100644 index bf85ab02f..000000000 --- a/extern/spongycastle/prov/src/main/java/org/spongycastle/x509/extension/SubjectKeyIdentifierStructure.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.spongycastle.x509.extension; - -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.PublicKey; - -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.x509.SubjectKeyIdentifier; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; - -/** - * A high level subject key identifier. - * @deprecated use JcaX509ExtensionUtils andSubjectKeyIdentifier.getInstance() - */ -public class SubjectKeyIdentifierStructure - extends SubjectKeyIdentifier -{ - /** - * Constructor which will take the byte[] returned from getExtensionValue() - * - * @param encodedValue a DER octet encoded string with the extension structure in it. - * @throws IOException on parsing errors. - */ - public SubjectKeyIdentifierStructure( - byte[] encodedValue) - throws IOException - { - super((ASN1OctetString)X509ExtensionUtil.fromExtensionValue(encodedValue)); - } - - private static ASN1OctetString fromPublicKey( - PublicKey pubKey) - throws InvalidKeyException - { - try - { - SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); - - return (ASN1OctetString)(new SubjectKeyIdentifier(info).toASN1Object()); - } - catch (Exception e) - { - throw new InvalidKeyException("Exception extracting key details: " + e.toString()); - } - } - - public SubjectKeyIdentifierStructure( - PublicKey pubKey) - throws InvalidKeyException - { - super(fromPublicKey(pubKey)); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/BouncyCastleProvider.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/BouncyCastleProvider.java index 87a086068..107e4c9f9 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/BouncyCastleProvider.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/BouncyCastleProvider.java @@ -42,7 +42,7 @@ import org.spongycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { - private static String info = "BouncyCastle Security Provider v1.50"; + private static String info = "BouncyCastle Security Provider v1.51"; public static final String PROVIDER_NAME = "SC"; @@ -115,7 +115,7 @@ public final class BouncyCastleProvider extends Provider */ public BouncyCastleProvider() { - super(PROVIDER_NAME, 1.50, info); + super(PROVIDER_NAME, 1.51, info); setup(); } diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java index fef14a6be..7f6955549 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.text.SimpleDateFormat; import org.spongycastle.jce.X509Principal; import org.spongycastle.jce.PrincipalUtil; @@ -49,11 +50,11 @@ import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.BERConstructedOctetString; import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.DEREnumerated; +import org.spongycastle.asn1.ASN1Enumerated; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.BasicConstraints; import org.spongycastle.asn1.x509.GeneralName; @@ -564,7 +565,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi private boolean processCertD1i( int index, List [] policyNodes, - DERObjectIdentifier pOid, + ASN1ObjectIdentifier pOid, Set pq) { List policyNodeVec = policyNodes[index - 1]; @@ -599,7 +600,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi private void processCertD1ii( int index, List [] policyNodes, - DERObjectIdentifier _poid, + ASN1ObjectIdentifier _poid, Set _pq) { List policyNodeVec = policyNodes[index - 1]; @@ -799,7 +800,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi } AlgorithmIdentifier workingAlgId = getAlgorithmIdentifier(workingPublicKey); - DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId(); + ASN1ObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId(); ASN1Encodable workingPublicKeyParameters = workingAlgId.getParameters(); // @@ -970,7 +971,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi while (e.hasMoreElements()) { PolicyInformation pInfo = PolicyInformation.getInstance(e.nextElement()); - DERObjectIdentifier pOid = pInfo.getPolicyIdentifier(); + ASN1ObjectIdentifier pOid = pInfo.getPolicyIdentifier(); pols.add(pOid.getId()); @@ -1039,9 +1040,9 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi { _policy = (String)_tmp; } - else if (_tmp instanceof DERObjectIdentifier) + else if (_tmp instanceof ASN1ObjectIdentifier) { - _policy = ((DERObjectIdentifier)_tmp).getId(); + _policy = ((ASN1ObjectIdentifier)_tmp).getId(); } else { @@ -1163,8 +1164,8 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi { ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j); - DERObjectIdentifier issuerDomainPolicy = (DERObjectIdentifier)mapping.getObjectAt(0); - DERObjectIdentifier subjectDomainPolicy = (DERObjectIdentifier)mapping.getObjectAt(1); + ASN1ObjectIdentifier issuerDomainPolicy = (ASN1ObjectIdentifier)mapping.getObjectAt(0); + ASN1ObjectIdentifier subjectDomainPolicy = (ASN1ObjectIdentifier)mapping.getObjectAt(1); if (ANY_POLICY.equals(issuerDomainPolicy.getId())) { @@ -1191,8 +1192,8 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi for (int j = 0; j < mappings.size(); j++) { ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j); - String id_p = ((DERObjectIdentifier)mapping.getObjectAt(0)).getId(); - String sd_p = ((DERObjectIdentifier)mapping.getObjectAt(1)).getId(); + String id_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(0)).getId(); + String sd_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(1)).getId(); Set tmp; if (!m_idp.containsKey(id_p)) @@ -1417,14 +1418,14 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi switch (constraint.getTagNo()) { case 0: - tmpInt = DERInteger.getInstance(constraint).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint).getValue().intValue(); if (tmpInt < explicitPolicy) { explicitPolicy = tmpInt; } break; case 1: - tmpInt = DERInteger.getInstance(constraint).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint).getValue().intValue(); if (tmpInt < policyMapping) { policyMapping = tmpInt; @@ -1437,7 +1438,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi // // (j) // - DERInteger iap = (DERInteger)getExtensionValue(cert, INHIBIT_ANY_POLICY); + ASN1Integer iap = (ASN1Integer)getExtensionValue(cert, INHIBIT_ANY_POLICY); if (iap != null) { @@ -1593,7 +1594,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi switch (constraint.getTagNo()) { case 0: - tmpInt = DERInteger.getInstance(constraint).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint).getValue().intValue(); if (tmpInt == 0) { explicitPolicy = 0; @@ -1893,7 +1894,7 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi if (crl_entry.hasExtensions()) { - DEREnumerated reasonCode = DEREnumerated.getInstance(getExtensionValue(crl_entry, X509Extensions.ReasonCode.getId())); + ASN1Enumerated reasonCode = ASN1Enumerated.getInstance(getExtensionValue(crl_entry, X509Extensions.ReasonCode.getId())); if (reasonCode != null) { reason = crlReasons[reasonCode.getValue().intValue()]; @@ -1931,8 +1932,8 @@ public class PKIXCertPathValidatorSpi extends CertPathValidatorSpi throw new AnnotatedException("can't extract issuer from certificate: " + e, e); } - baseSelect.setMinCRLNumber(((DERInteger)dci).getPositiveValue()); - baseSelect.setMaxCRLNumber(((DERInteger)getExtensionValue(crl, CRL_NUMBER)).getPositiveValue().subtract(BigInteger.valueOf(1))); + baseSelect.setMinCRLNumber(((ASN1Integer)dci).getPositiveValue()); + baseSelect.setMaxCRLNumber(((ASN1Integer)getExtensionValue(crl, CRL_NUMBER)).getPositiveValue().subtract(BigInteger.valueOf(1))); boolean foundBase = false; Iterator it = findCRLs(baseSelect, paramsPKIX.getCertStores()).iterator(); diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/X509CRLObject.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/X509CRLObject.java index b31938bd7..ff7745287 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/X509CRLObject.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/jce/provider/X509CRLObject.java @@ -26,7 +26,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.CRLDistPoint; @@ -430,7 +430,7 @@ public class X509CRLObject if (oid.equals(Extension.cRLNumber)) { buf.append( - new CRLNumber(DERInteger.getInstance( + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } @@ -438,7 +438,7 @@ public class X509CRLObject { buf.append( "Base CRL: " - + new CRLNumber(DERInteger.getInstance( + + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/ocsp/OCSPUtil.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/ocsp/OCSPUtil.java deleted file mode 100644 index b134f1458..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/ocsp/OCSPUtil.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.spongycastle.ocsp; - -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; -import org.spongycastle.asn1.nist.NISTObjectIdentifiers; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x9.X9ObjectIdentifiers; -import org.spongycastle.util.Strings; - -import java.security.InvalidAlgorithmParameterException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Signature; -import java.security.cert.CertStore; -import java.security.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -class OCSPUtil -{ - private static Hashtable algorithms = new Hashtable(); - private static Hashtable oids = new Hashtable(); - private static Set noParams = new HashSet(); - - static - { - algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); - algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); - algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); - algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); - algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); - algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); - algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - - oids.put(PKCSObjectIdentifiers.md2WithRSAEncryption, "MD2WITHRSA"); - oids.put(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160, "RIPEMD160WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128, "RIPEMD128WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256, "RIPEMD256WITHRSA"); - oids.put(X9ObjectIdentifiers.id_dsa_with_sha1, "SHA1WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha224, "SHA224WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha256, "SHA256WITHDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512WITHECDSA"); - oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); - - // - // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. - // The parameters field SHALL be NULL for RSA based signature algorithms. - // - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); - noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); - noParams.add(NISTObjectIdentifiers.dsa_with_sha224); - noParams.add(NISTObjectIdentifiers.dsa_with_sha256); - } - - static DERObjectIdentifier getAlgorithmOID( - String algorithmName) - { - algorithmName = Strings.toUpperCase(algorithmName); - - if (algorithms.containsKey(algorithmName)) - { - return (DERObjectIdentifier)algorithms.get(algorithmName); - } - - return new DERObjectIdentifier(algorithmName); - } - - static String getAlgorithmName( - DERObjectIdentifier oid) - { - if (oids.containsKey(oid)) - { - return (String)oids.get(oid); - } - - return oid.getId(); - } - - static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid) - { - if (noParams.contains(sigOid)) - { - return new AlgorithmIdentifier(sigOid); - } - else - { - return new AlgorithmIdentifier(sigOid, new DERNull()); - } - } - - static Iterator getAlgNames() - { - Enumeration e = algorithms.keys(); - List l = new ArrayList(); - - while (e.hasMoreElements()) - { - l.add(e.nextElement()); - } - - return l.iterator(); - } - - static CertStore createCertStoreInstance(String type, CertStoreParameters params, String provider) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return CertStore.getInstance(type, params); - } - - return CertStore.getInstance(type, params, provider); - } - - static MessageDigest createDigestInstance(String digestName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return MessageDigest.getInstance(digestName); - } - - return MessageDigest.getInstance(digestName, provider); - } - - static Signature createSignatureInstance(String sigName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return Signature.getInstance(sigName); - } - - return Signature.getInstance(sigName, provider); - } - - static CertificateFactory createX509CertificateFactory(String provider) - throws CertificateException, NoSuchProviderException - { - if (provider == null) - { - return CertificateFactory.getInstance("X.509"); - } - - return CertificateFactory.getInstance("X.509", provider); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509Util.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509Util.java index b61fd157f..74aa897bb 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509Util.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509Util.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -134,21 +134,21 @@ class X509Util new ASN1Integer(1)); } - static DERObjectIdentifier getAlgorithmOID( + static ASN1ObjectIdentifier getAlgorithmOID( String algorithmName) { algorithmName = Strings.toUpperCase(algorithmName); if (algorithms.containsKey(algorithmName)) { - return (DERObjectIdentifier)algorithms.get(algorithmName); + return (ASN1ObjectIdentifier)algorithms.get(algorithmName); } - return new DERObjectIdentifier(algorithmName); + return new ASN1ObjectIdentifier(algorithmName); } static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String algorithmName) { if (noParams.contains(sigOid)) @@ -204,7 +204,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, PrivateKey key, SecureRandom random, @@ -235,7 +235,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, String provider, PrivateKey key, diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V1CertificateGenerator.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V1CertificateGenerator.java index 58302d731..95cf7d6ad 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V1CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V1CertificateGenerator.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; @@ -40,7 +40,7 @@ import org.spongycastle.jce.provider.X509CertificateObject; public class X509V1CertificateGenerator { private V1TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java index 2b1bc6bf7..9aae6e850 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2AttributeCertificateGenerator.java @@ -20,7 +20,7 @@ import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.DERSequence; @@ -40,7 +40,7 @@ import org.spongycastle.util.Strings; public class X509V2AttributeCertificateGenerator { private V2AttributeCertificateInfoGenerator acInfoGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private Hashtable extensions = null; @@ -49,18 +49,18 @@ public class X509V2AttributeCertificateGenerator static { - algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); - algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); - algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2")); - algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2")); - algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); - algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); - algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1")); - algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1")); + algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD5WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("MD5WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("SHA1WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("SHA1WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("RIPEMD160WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.3.36.3.3.1.2")); + algorithms.put("RIPEMD160WITHRSA", new ASN1ObjectIdentifier("1.3.36.3.3.1.2")); + algorithms.put("SHA1WITHDSA", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("DSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("SHA1WITHECDSA", new ASN1ObjectIdentifier("1.2.840.10045.4.1")); + algorithms.put("ECDSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10045.4.1")); } public X509V2AttributeCertificateGenerator() @@ -131,7 +131,7 @@ public class X509V2AttributeCertificateGenerator { this.signatureAlgorithm = signatureAlgorithm; - sigOID = (DERObjectIdentifier)algorithms.get(Strings.toUpperCase(signatureAlgorithm)); + sigOID = (ASN1ObjectIdentifier)algorithms.get(Strings.toUpperCase(signatureAlgorithm)); if (sigOID == null) { @@ -188,7 +188,7 @@ public class X509V2AttributeCertificateGenerator extOrdering = new Vector(); } - DERObjectIdentifier oid = new DERObjectIdentifier(OID); + ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(OID); extensions.put(oid, new X509Extension(critical, new DEROctetString(value))); extOrdering.addElement(oid); diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2CRLGenerator.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2CRLGenerator.java index 419f9706f..ac9ad6ddb 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2CRLGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V2CRLGenerator.java @@ -24,7 +24,6 @@ import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.CertificateList; @@ -44,7 +43,7 @@ import org.spongycastle.jce.provider.X509CRLObject; public class X509V2CRLGenerator { private V2TBSCertListGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -177,14 +176,14 @@ public class X509V2CRLGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -199,14 +198,14 @@ public class X509V2CRLGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { diff --git a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V3CertificateGenerator.java b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V3CertificateGenerator.java index 2ee754ad6..1a0dc95be 100644 --- a/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V3CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.1/org/spongycastle/x509/X509V3CertificateGenerator.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; @@ -42,7 +42,7 @@ import org.spongycastle.x509.extension.X509ExtensionUtil; public class X509V3CertificateGenerator { private V3TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -192,14 +192,14 @@ public class X509V3CertificateGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -216,14 +216,14 @@ public class X509V3CertificateGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { @@ -266,7 +266,7 @@ public class X509V3CertificateGenerator * @throws CertificateParsingException if the extension cannot be extracted. */ public void copyAndAddExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, X509Certificate cert) throws CertificateParsingException diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java index bd300db67..dac30008b 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java @@ -12,7 +12,7 @@ import java.util.Set; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DEREnumerated; +import org.spongycastle.asn1.ASN1Enumerated; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.CRLReason; @@ -262,7 +262,7 @@ class X509CRLEntryObject extends X509CRLEntry { if (oid.equals(X509Extension.reasonCode)) { - buf.append(CRLReason.getInstance(DEREnumerated.getInstance(dIn.readObject()))).append(nl); + buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl); } else if (oid.equals(X509Extension.certificateIssuer)) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java index ff88a36f0..f2b5f5d8d 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java @@ -26,7 +26,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.CRLDistPoint; @@ -432,7 +432,7 @@ class X509CRLObject if (oid.equals(Extension.cRLNumber)) { buf.append( - new CRLNumber(DERInteger.getInstance( + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } @@ -440,7 +440,7 @@ class X509CRLObject { buf.append( "Base CRL: " - + new CRLNumber(DERInteger.getInstance( + + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java index 6395d2e85..e74ced7f5 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java @@ -8,7 +8,7 @@ import java.security.SignatureException; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Null; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -75,7 +75,7 @@ class X509SignatureUtil * representations rather the the algorithm identifier (if possible). */ private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index 651a471cb..9875bd140 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -71,6 +71,8 @@ import org.spongycastle.asn1.x509.Extension; import org.spongycastle.asn1.x509.SubjectKeyIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x509.X509ObjectIdentifiers; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.SHA1Digest; import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.spongycastle.jcajce.provider.util.SecretKeyUtil; import org.spongycastle.jce.interfaces.BCKeyStore; @@ -188,10 +190,9 @@ public class PKCS12KeyStoreSpi { try { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded())); + SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()); - return new SubjectKeyIdentifier(info); + return new SubjectKeyIdentifier(getDigest(info)); } catch (Exception e) { @@ -199,6 +200,17 @@ public class PKCS12KeyStoreSpi } } + private static byte[] getDigest(SubjectPublicKeyInfo spki) + { + Digest digest = new SHA1Digest(); + byte[] resBuf = new byte[digest.getDigestSize()]; + + byte[] bytes = spki.getPublicKeyData().getBytes(); + digest.update(bytes, 0, bytes.length); + digest.doFinal(resBuf, 0); + return resBuf; + } + public void setRandom( SecureRandom rand) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java index 34ce128e9..d188bf696 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java @@ -333,7 +333,9 @@ public class BaseBlockCipher { if (engineProvider != null) { - // Nonce restricted to max 120 bits over 128 bit block cipher since draft-irtf-cfrg-ocb-03 + /* + * RFC 7253 4.2. Nonce is a string of no more than 120 bits + */ ivLength = 15; cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get())); } diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/ProviderJcaJceHelper.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java similarity index 97% rename from extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/ProviderJcaJceHelper.java rename to extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java index 02580c0d4..5f211dbe2 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/ProviderJcaJceHelper.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jcajce/util/ProviderJcaJceHelper.java @@ -1,4 +1,4 @@ -package org.spongycastle.jcajce; +package org.spongycastle.jcajce.util; import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; @@ -19,6 +19,8 @@ import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; +import org.spongycastle.jcajce.util.JcaJceHelper; + public class ProviderJcaJceHelper implements JcaJceHelper { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/PKCS10CertificationRequest.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/PKCS10CertificationRequest.java index 051f2d41f..b9bc6e521 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/PKCS10CertificationRequest.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/PKCS10CertificationRequest.java @@ -26,7 +26,7 @@ import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1Set; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -78,13 +78,13 @@ public class PKCS10CertificationRequest static { - algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2")); - algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4")); - algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5")); - algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("MD2WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD2WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.2")); + algorithms.put("MD5WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("MD5WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("RSAWITHMD5", new ASN1ObjectIdentifier("1.2.840.113549.1.1.4")); + algorithms.put("SHA1WITHRSAENCRYPTION", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("SHA1WITHRSA", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); @@ -98,15 +98,15 @@ public class PKCS10CertificationRequest algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS); - algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5")); + algorithms.put("RSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.113549.1.1.5")); algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3")); - algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("SHA1WITHDSA", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); + algorithms.put("DSAWITHSHA1", new ASN1ObjectIdentifier("1.2.840.10040.4.3")); algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384); @@ -126,7 +126,7 @@ public class PKCS10CertificationRequest // // reverse mappings // - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA"); oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA"); oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA"); oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA"); @@ -134,9 +134,9 @@ public class PKCS10CertificationRequest oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, "GOST3411WITHECGOST3410"); - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); - oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); - oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA"); + oids.put(new ASN1ObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA"); oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA"); @@ -260,13 +260,13 @@ public class PKCS10CertificationRequest InvalidKeyException, SignatureException { String algorithmName = Strings.toUpperCase(signatureAlgorithm); - DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(algorithmName); + ASN1ObjectIdentifier sigOID = (ASN1ObjectIdentifier)algorithms.get(algorithmName); if (sigOID == null) { try { - sigOID = new DERObjectIdentifier(algorithmName); + sigOID = new ASN1ObjectIdentifier(algorithmName); } catch (Exception e) { @@ -533,7 +533,7 @@ public class PKCS10CertificationRequest } private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java index 6ddd43356..4a377ed36 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CRLSelector.java @@ -16,7 +16,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Object; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.x509.X509Extensions; import org.spongycastle.asn1.x509.X509Name; import org.spongycastle.jce.PrincipalUtil; @@ -562,7 +562,7 @@ public class X509CRLSelector implements CRLSelector ((ASN1OctetString)derInputStream.readObject()) .getOctets()); derInputStream = new ASN1InputStream(inStream); - BigInteger crlNumber = ((DERInteger)derInputStream.readObject()) + BigInteger crlNumber = ((ASN1Integer)derInputStream.readObject()) .getPositiveValue(); if (minCRL != null && minCRL.compareTo(crlNumber) > 0) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CertSelector.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CertSelector.java index 0f1f814dd..0b288faa4 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CertSelector.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/cert/X509CertSelector.java @@ -27,6 +27,7 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -2155,7 +2156,7 @@ public class X509CertSelector implements CertSelector // TODO fix this, Sequence contains tagged objects ASN1Sequence derObject = (ASN1Sequence)derInputStream .readObject(); - DERGeneralizedTime derDate = DERGeneralizedTime + ASN1GeneralizedTime derDate = ASN1GeneralizedTime .getInstance(derObject.getObjectAt(0)); SimpleDateFormat dateF = new SimpleDateFormat( "yyyyMMddHHmmssZ"); @@ -2163,7 +2164,7 @@ public class X509CertSelector implements CertSelector { return false; } - derDate = DERGeneralizedTime.getInstance(derObject + derDate = ASN1GeneralizedTime.getInstance(derObject .getObjectAt(1)); if (privateKeyValid.after(dateF.parse(derDate.getTime()))) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/CertPathValidatorUtilities.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/CertPathValidatorUtilities.java index 5ee182475..40bf81dab 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/CertPathValidatorUtilities.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/CertPathValidatorUtilities.java @@ -42,10 +42,10 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1OutputStream; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DEREnumerated; -import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.ASN1Enumerated; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.isismtt.ISISMTTObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -477,7 +477,7 @@ catch (Exception e) protected static boolean processCertD1i( int index, List[] policyNodes, - DERObjectIdentifier pOid, + ASN1ObjectIdentifier pOid, Set pq) { List policyNodeVec = policyNodes[index - 1]; @@ -512,7 +512,7 @@ catch (Exception e) protected static void processCertD1ii( int index, List[] policyNodes, - DERObjectIdentifier _poid, + ASN1ObjectIdentifier _poid, Set _pq) { List policyNodeVec = policyNodes[index - 1]; @@ -1008,12 +1008,12 @@ catch (Exception e) } } - DEREnumerated reasonCode = null; + ASN1Enumerated reasonCode = null; if (crl_entry.hasExtensions()) { try { - reasonCode = DEREnumerated + reasonCode = ASN1Enumerated .getInstance(CertPathValidatorUtilities .getExtensionValue(crl_entry, X509Extension.reasonCode.getId())); @@ -1234,13 +1234,13 @@ catch (Exception e) { if (index - 1 == 0) { - DERGeneralizedTime dateOfCertgen = null; + ASN1GeneralizedTime dateOfCertgen = null; try { byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId()); if (extBytes != null) { - dateOfCertgen = DERGeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); + dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); } } catch (IOException e) diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKAlgorithmParameters.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKAlgorithmParameters.java index cd56e0543..9b33841f2 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKAlgorithmParameters.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKAlgorithmParameters.java @@ -14,7 +14,7 @@ import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.DEROutputStream; import org.spongycastle.asn1.DERSequence; @@ -547,7 +547,7 @@ public abstract class JDKAlgorithmParameters v.add(new DEROctetString(currentSpec.getDerivationV())); v.add(new DEROctetString(currentSpec.getEncodingV())); - v.add(new DERInteger(currentSpec.getMacKeySize())); + v.add(new ASN1Integer(currentSpec.getMacKeySize())); dOut.writeObject(new DERSequence(v)); dOut.close(); @@ -608,7 +608,7 @@ public abstract class JDKAlgorithmParameters this.currentSpec = new IESParameterSpec( ((ASN1OctetString)s.getObjectAt(0)).getOctets(), ((ASN1OctetString)s.getObjectAt(0)).getOctets(), - ((DERInteger)s.getObjectAt(0)).getValue().intValue()); + ((ASN1Integer)s.getObjectAt(0)).getValue().intValue()); } catch (ClassCastException e) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java deleted file mode 100644 index 1c8602377..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java +++ /dev/null @@ -1,1586 +0,0 @@ -package org.spongycastle.jce.provider; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.Key; -import java.security.KeyStoreException; -import java.security.KeyStoreSpi; -import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.ASN1Set; -import org.spongycastle.asn1.BERConstructedOctetString; -import org.spongycastle.asn1.BEROutputStream; -import org.spongycastle.asn1.DERBMPString; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.DEROutputStream; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.DERSet; -import org.spongycastle.asn1.pkcs.AuthenticatedSafe; -import org.spongycastle.asn1.pkcs.CertBag; -import org.spongycastle.asn1.pkcs.ContentInfo; -import org.spongycastle.asn1.pkcs.EncryptedData; -import org.spongycastle.asn1.pkcs.MacData; -import org.spongycastle.asn1.pkcs.PKCS12PBEParams; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.pkcs.Pfx; -import org.spongycastle.asn1.pkcs.SafeBag; -import org.spongycastle.asn1.util.ASN1Dump; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; -import org.spongycastle.asn1.x509.DigestInfo; -import org.spongycastle.asn1.x509.SubjectKeyIdentifier; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.asn1.x509.X509ObjectIdentifiers; -import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; -import org.spongycastle.jce.interfaces.BCKeyStore; -import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; -import org.spongycastle.util.Arrays; -import org.spongycastle.util.Strings; -import org.spongycastle.util.encoders.Hex; - -public class JDKPKCS12KeyStore - extends KeyStoreSpi - implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore -{ - private static final int SALT_SIZE = 20; - private static final int MIN_ITERATIONS = 1024; - - private IgnoresCaseHashtable keys = new IgnoresCaseHashtable(); - private Hashtable localIds = new Hashtable(); - private IgnoresCaseHashtable certs = new IgnoresCaseHashtable(); - private Hashtable chainCerts = new Hashtable(); - private Hashtable keyCerts = new Hashtable(); - - private static final String bcProvider = "SC"; - - // - // generic object types - // - static final int NULL = 0; - static final int CERTIFICATE = 1; - static final int KEY = 2; - static final int SECRET = 3; - static final int SEALED = 4; - - // - // key types - // - static final int KEY_PRIVATE = 0; - static final int KEY_PUBLIC = 1; - static final int KEY_SECRET = 2; - - protected SecureRandom random = new SecureRandom(); - - // use of final causes problems with JDK 1.2 compiler - private CertificateFactory certFact; - private ASN1ObjectIdentifier keyAlgorithm; - private ASN1ObjectIdentifier certAlgorithm; - - private class CertId - { - byte[] id; - - CertId( - PublicKey key) - { - this.id = createSubjectKeyId(key).getKeyIdentifier(); - } - - CertId( - byte[] id) - { - this.id = id; - } - - public int hashCode() - { - return Arrays.hashCode(id); - } - - public boolean equals( - Object o) - { - if (o == this) - { - return true; - } - - if (!(o instanceof CertId)) - { - return false; - } - - CertId cId = (CertId)o; - - return Arrays.areEqual(id, cId.id); - } - } - - public JDKPKCS12KeyStore( - String provider, - ASN1ObjectIdentifier keyAlgorithm, - ASN1ObjectIdentifier certAlgorithm) - { - this.keyAlgorithm = keyAlgorithm; - this.certAlgorithm = certAlgorithm; - - try - { - if (provider != null) - { - certFact = CertificateFactory.getInstance("X.509", provider); - } - else - { - certFact = CertificateFactory.getInstance("X.509"); - } - } - catch (Exception e) - { - throw new IllegalArgumentException("can't create cert factory - " + e.toString()); - } - } - - private SubjectKeyIdentifier createSubjectKeyId( - PublicKey pubKey) - { - try - { - SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( - (ASN1Sequence) ASN1Primitive.fromByteArray(pubKey.getEncoded())); - - return new SubjectKeyIdentifier(info); - } - catch (Exception e) - { - throw new RuntimeException("error creating key"); - } - } - - public void setRandom( - SecureRandom rand) - { - this.random = rand; - } - - public Enumeration engineAliases() - { - Hashtable tab = new Hashtable(); - - Enumeration e = certs.keys(); - while (e.hasMoreElements()) - { - tab.put(e.nextElement(), "cert"); - } - - e = keys.keys(); - while (e.hasMoreElements()) - { - String a = (String)e.nextElement(); - if (tab.get(a) == null) - { - tab.put(a, "key"); - } - } - - return tab.keys(); - } - - public boolean engineContainsAlias( - String alias) - { - return (certs.get(alias) != null || keys.get(alias) != null); - } - - /** - * this is not quite complete - we should follow up on the chain, a bit - * tricky if a certificate appears in more than one chain... - */ - public void engineDeleteEntry( - String alias) - throws KeyStoreException - { - Key k = (Key)keys.remove(alias); - - Certificate c = (Certificate)certs.remove(alias); - - if (c != null) - { - chainCerts.remove(new CertId(c.getPublicKey())); - } - - if (k != null) - { - String id = (String)localIds.remove(alias); - if (id != null) - { - c = (Certificate)keyCerts.remove(id); - } - if (c != null) - { - chainCerts.remove(new CertId(c.getPublicKey())); - } - } - - if (c == null && k == null) - { - throw new KeyStoreException("no such entry as " + alias); - } - } - - /** - * simply return the cert for the private key - */ - public Certificate engineGetCertificate( - String alias) - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getCertificate."); - } - - Certificate c = (Certificate)certs.get(alias); - - // - // look up the key table - and try the local key id - // - if (c == null) - { - String id = (String)localIds.get(alias); - if (id != null) - { - c = (Certificate)keyCerts.get(id); - } - else - { - c = (Certificate)keyCerts.get(alias); - } - } - - return c; - } - - public String engineGetCertificateAlias( - Certificate cert) - { - Enumeration c = certs.elements(); - Enumeration k = certs.keys(); - - while (c.hasMoreElements()) - { - Certificate tc = (Certificate)c.nextElement(); - String ta = (String)k.nextElement(); - - if (tc.equals(cert)) - { - return ta; - } - } - - c = keyCerts.elements(); - k = keyCerts.keys(); - - while (c.hasMoreElements()) - { - Certificate tc = (Certificate)c.nextElement(); - String ta = (String)k.nextElement(); - - if (tc.equals(cert)) - { - return ta; - } - } - - return null; - } - - public Certificate[] engineGetCertificateChain( - String alias) - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getCertificateChain."); - } - - if (!engineIsKeyEntry(alias)) - { - return null; - } - - Certificate c = engineGetCertificate(alias); - - if (c != null) - { - Vector cs = new Vector(); - - while (c != null) - { - X509Certificate x509c = (X509Certificate)c; - Certificate nextC = null; - - byte[] bytes = x509c.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId()); - if (bytes != null) - { - try - { - ASN1InputStream aIn = new ASN1InputStream(bytes); - - byte[] authBytes = ((ASN1OctetString)aIn.readObject()).getOctets(); - aIn = new ASN1InputStream(authBytes); - - AuthorityKeyIdentifier id = AuthorityKeyIdentifier.getInstance(aIn.readObject()); - if (id.getKeyIdentifier() != null) - { - nextC = (Certificate)chainCerts.get(new CertId(id.getKeyIdentifier())); - } - - } - catch (IOException e) - { - throw new RuntimeException(e.toString()); - } - } - - if (nextC == null) - { - // - // no authority key id, try the Issuer DN - // - Principal i = x509c.getIssuerDN(); - Principal s = x509c.getSubjectDN(); - - if (!i.equals(s)) - { - Enumeration e = chainCerts.keys(); - - while (e.hasMoreElements()) - { - X509Certificate crt = (X509Certificate)chainCerts.get(e.nextElement()); - Principal sub = crt.getSubjectDN(); - if (sub.equals(i)) - { - try - { - x509c.verify(crt.getPublicKey()); - nextC = crt; - break; - } - catch (Exception ex) - { - // continue - } - } - } - } - } - - cs.addElement(c); - if (nextC != c) // self signed - end of the chain - { - c = nextC; - } - else - { - c = null; - } - } - - Certificate[] certChain = new Certificate[cs.size()]; - - for (int i = 0; i != certChain.length; i++) - { - certChain[i] = (Certificate)cs.elementAt(i); - } - - return certChain; - } - - return null; - } - - public Date engineGetCreationDate(String alias) - { - return new Date(); - } - - public Key engineGetKey( - String alias, - char[] password) - throws NoSuchAlgorithmException, UnrecoverableKeyException - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getKey."); - } - - return (Key)keys.get(alias); - } - - public boolean engineIsCertificateEntry( - String alias) - { - return (certs.get(alias) != null && keys.get(alias) == null); - } - - public boolean engineIsKeyEntry( - String alias) - { - return (keys.get(alias) != null); - } - - public void engineSetCertificateEntry( - String alias, - Certificate cert) - throws KeyStoreException - { - if (keys.get(alias) != null) - { - throw new KeyStoreException("There is a key entry with the name " + alias + "."); - } - - certs.put(alias, cert); - chainCerts.put(new CertId(cert.getPublicKey()), cert); - } - - public void engineSetKeyEntry( - String alias, - byte[] key, - Certificate[] chain) - throws KeyStoreException - { - throw new RuntimeException("operation not supported"); - } - - public void engineSetKeyEntry( - String alias, - Key key, - char[] password, - Certificate[] chain) - throws KeyStoreException - { - if ((key instanceof PrivateKey) && (chain == null)) - { - throw new KeyStoreException("no certificate chain for private key"); - } - - if (keys.get(alias) != null) - { - engineDeleteEntry(alias); - } - - keys.put(alias, key); - certs.put(alias, chain[0]); - - for (int i = 0; i != chain.length; i++) - { - chainCerts.put(new CertId(chain[i].getPublicKey()), chain[i]); - } - } - - public int engineSize() - { - Hashtable tab = new Hashtable(); - - Enumeration e = certs.keys(); - while (e.hasMoreElements()) - { - tab.put(e.nextElement(), "cert"); - } - - e = keys.keys(); - while (e.hasMoreElements()) - { - String a = (String)e.nextElement(); - if (tab.get(a) == null) - { - tab.put(a, "key"); - } - } - - return tab.size(); - } - - protected PrivateKey unwrapKey( - AlgorithmIdentifier algId, - byte[] data, - char[] password, - boolean wrongPKCS12Zero) - throws IOException - { - String algorithm = algId.getAlgorithm().getId(); - PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); - - PBEKeySpec pbeSpec = new PBEKeySpec(password); - PrivateKey out; - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance( - algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - - SecretKey k = keyFact.generateSecret(pbeSpec); - - ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - - cipher.init(Cipher.UNWRAP_MODE, k, defParams); - - // we pass "" as the key algorithm type as it is unknown at this point - out = (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY); - } - catch (Exception e) - { - throw new IOException("exception unwrapping private key - " + e.toString()); - } - - return out; - } - - protected byte[] wrapKey( - String algorithm, - Key key, - PKCS12PBEParams pbeParams, - char[] password) - throws IOException - { - PBEKeySpec pbeSpec = new PBEKeySpec(password); - byte[] out; - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance( - algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - - cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams); - - out = cipher.wrap(key); - } - catch (Exception e) - { - throw new IOException("exception encrypting data - " + e.toString()); - } - - return out; - } - - protected byte[] cryptData( - boolean forEncryption, - AlgorithmIdentifier algId, - char[] password, - boolean wrongPKCS12Zero, - byte[] data) - throws IOException - { - String algorithm = algId.getObjectId().getId(); - PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec); - - key.setTryWrongPKCS12Zero(wrongPKCS12Zero); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; - cipher.init(mode, key, defParams); - return cipher.doFinal(data); - } - catch (Exception e) - { - throw new IOException("exception decrypting data - " + e.toString()); - } - } - - public void engineLoad( - InputStream stream, - char[] password) - throws IOException - { - if (stream == null) // just initialising - { - return; - } - - if (password == null) - { - throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); - } - - BufferedInputStream bufIn = new BufferedInputStream(stream); - - bufIn.mark(10); - - int head = bufIn.read(); - - if (head != 0x30) - { - throw new IOException("stream does not represent a PKCS12 key store"); - } - - bufIn.reset(); - - ASN1InputStream bIn = new ASN1InputStream(bufIn); - ASN1Sequence obj = (ASN1Sequence)bIn.readObject(); - Pfx bag = Pfx.getInstance(obj); - ContentInfo info = bag.getAuthSafe(); - Vector chain = new Vector(); - boolean unmarkedKey = false; - boolean wrongPKCS12Zero = false; - - if (bag.getMacData() != null) // check the mac code - { - MacData mData = bag.getMacData(); - DigestInfo dInfo = mData.getMac(); - AlgorithmIdentifier algId = dInfo.getAlgorithmId(); - byte[] salt = mData.getSalt(); - int itCount = mData.getIterationCount().intValue(); - - byte[] data = ((ASN1OctetString)info.getContent()).getOctets(); - - try - { - byte[] res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, false, data); - byte[] dig = dInfo.getDigest(); - - if (!Arrays.constantTimeAreEqual(res, dig)) - { - if (password.length > 0) - { - throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); - } - - // Try with incorrect zero length password - res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, true, data); - - if (!Arrays.constantTimeAreEqual(res, dig)) - { - throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); - } - - wrongPKCS12Zero = true; - } - } - catch (IOException e) - { - throw e; - } - catch (Exception e) - { - throw new IOException("error constructing MAC: " + e.toString()); - } - } - - keys = new IgnoresCaseHashtable(); - localIds = new Hashtable(); - - if (info.getContentType().equals(data)) - { - bIn = new ASN1InputStream(((ASN1OctetString)info.getContent()).getOctets()); - - AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(bIn.readObject()); - ContentInfo[] c = authSafe.getContentInfo(); - - for (int i = 0; i != c.length; i++) - { - if (c[i].getContentType().equals(data)) - { - ASN1InputStream dIn = new ASN1InputStream(((ASN1OctetString)c[i].getContent()).getOctets()); - ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); - - for (int j = 0; j != seq.size(); j++) - { - SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); - if (b.getBagId().equals(pkcs8ShroudedKeyBag)) - { - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); - PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - if (b.getBagAttributes() != null) - { - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); - ASN1Primitive attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Primitive)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - } - - if (localId != null) - { - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else - { - unmarkedKey = true; - keys.put("unmarked", privKey); - } - } - else if (b.getBagId().equals(certBag)) - { - chain.addElement(b); - } - else - { - System.out.println("extra in data " + b.getBagId()); - System.out.println(ASN1Dump.dumpAsString(b)); - } - } - } - else if (c[i].getContentType().equals(encryptedData)) - { - EncryptedData d = EncryptedData.getInstance(c[i].getContent()); - byte[] octets = cryptData(false, d.getEncryptionAlgorithm(), - password, wrongPKCS12Zero, d.getContent().getOctets()); - ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(octets); - - for (int j = 0; j != seq.size(); j++) - { - SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); - - if (b.getBagId().equals(certBag)) - { - chain.addElement(b); - } - else if (b.getBagId().equals(pkcs8ShroudedKeyBag)) - { - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); - PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet= (ASN1Set)sq.getObjectAt(1); - ASN1Primitive attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Primitive)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else if (b.getBagId().equals(keyBag)) - { - org.spongycastle.asn1.pkcs.PrivateKeyInfo kInfo = new org.spongycastle.asn1.pkcs.PrivateKeyInfo((ASN1Sequence)b.getBagValue()); - PrivateKey privKey = BouncyCastleProvider.getPrivateKey(kInfo); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); - ASN1Primitive attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Primitive)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else - { - System.out.println("extra in encryptedData " + b.getBagId()); - System.out.println(ASN1Dump.dumpAsString(b)); - } - } - } - else - { - System.out.println("extra " + c[i].getContentType().getId()); - System.out.println("extra " + ASN1Dump.dumpAsString(c[i].getContent())); - } - } - } - - certs = new IgnoresCaseHashtable(); - chainCerts = new Hashtable(); - keyCerts = new Hashtable(); - - for (int i = 0; i != chain.size(); i++) - { - SafeBag b = (SafeBag)chain.elementAt(i); - CertBag cb = CertBag.getInstance(b.getBagValue()); - - if (!cb.getCertId().equals(x509Certificate)) - { - throw new RuntimeException("Unsupported certificate type: " + cb.getCertId()); - } - - Certificate cert; - - try - { - ByteArrayInputStream cIn = new ByteArrayInputStream( - ((ASN1OctetString)cb.getCertValue()).getOctets()); - cert = certFact.generateCertificate(cIn); - } - catch (Exception e) - { - throw new RuntimeException(e.toString()); - } - - // - // set the attributes - // - ASN1OctetString localId = null; - String alias = null; - - if (b.getBagAttributes() != null) - { - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Primitive attr = (ASN1Primitive)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0); - PKCS12BagAttributeCarrier bagAttr = null; - - if (cert instanceof PKCS12BagAttributeCarrier) - { - bagAttr = (PKCS12BagAttributeCarrier)cert; - - ASN1Encodable existing = bagAttr.getBagAttribute(oid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(oid, attr); - } - } - - if (oid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - } - else if (oid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - } - - chainCerts.put(new CertId(cert.getPublicKey()), cert); - - if (unmarkedKey) - { - if (keyCerts.isEmpty()) - { - String name = new String(Hex.encode(createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier())); - - keyCerts.put(name, cert); - keys.put(name, keys.remove("unmarked")); - } - } - else - { - // - // the local key id needs to override the friendly name - // - if (localId != null) - { - String name = new String(Hex.encode(localId.getOctets())); - - keyCerts.put(name, cert); - } - if (alias != null) - { - certs.put(alias, cert); - } - } - } - } - - public void engineStore(OutputStream stream, char[] password) - throws IOException - { - doStore(stream, password, false); - } - - private void doStore(OutputStream stream, char[] password, boolean useDEREncoding) - throws IOException - { - if (password == null) - { - throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); - } - - // - // handle the key - // - ASN1EncodableVector keyS = new ASN1EncodableVector(); - - - Enumeration ks = keys.keys(); - - while (ks.hasMoreElements()) - { - byte[] kSalt = new byte[SALT_SIZE]; - - random.nextBytes(kSalt); - - String name = (String)ks.nextElement(); - PrivateKey privKey = (PrivateKey)keys.get(name); - PKCS12PBEParams kParams = new PKCS12PBEParams(kSalt, MIN_ITERATIONS); - byte[] kBytes = wrapKey(keyAlgorithm.getId(), privKey, kParams, password); - AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(keyAlgorithm, kParams.toASN1Primitive()); - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo kInfo = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, kBytes); - boolean attrSet = false; - ASN1EncodableVector kName = new ASN1EncodableVector(); - - if (privKey instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)privKey; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(name)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); - } - - // - // make sure we have a local key-id - // - if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) - { - Certificate ct = engineGetCertificate(name); - - bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(ct.getPublicKey())); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - ASN1EncodableVector kSeq = new ASN1EncodableVector(); - - kSeq.add(oid); - kSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - - attrSet = true; - - kName.add(new DERSequence(kSeq)); - } - } - - if (!attrSet) - { - // - // set a default friendly name (from the key id) and local id - // - ASN1EncodableVector kSeq = new ASN1EncodableVector(); - Certificate ct = engineGetCertificate(name); - - kSeq.add(pkcs_9_at_localKeyId); - kSeq.add(new DERSet(createSubjectKeyId(ct.getPublicKey()))); - - kName.add(new DERSequence(kSeq)); - - kSeq = new ASN1EncodableVector(); - - kSeq.add(pkcs_9_at_friendlyName); - kSeq.add(new DERSet(new DERBMPString(name))); - - kName.add(new DERSequence(kSeq)); - } - - SafeBag kBag = new SafeBag(pkcs8ShroudedKeyBag, kInfo.toASN1Primitive(), new DERSet(kName)); - keyS.add(kBag); - } - - byte[] keySEncoded = new DERSequence(keyS).getEncoded(ASN1Encoding.DER); - BERConstructedOctetString keyString = new BERConstructedOctetString(keySEncoded); - - // - // certificate processing - // - byte[] cSalt = new byte[SALT_SIZE]; - - random.nextBytes(cSalt); - - ASN1EncodableVector certSeq = new ASN1EncodableVector(); - PKCS12PBEParams cParams = new PKCS12PBEParams(cSalt, MIN_ITERATIONS); - AlgorithmIdentifier cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Primitive()); - Hashtable doneCerts = new Hashtable(); - - Enumeration cs = keys.keys(); - while (cs.hasMoreElements()) - { - try - { - String name = (String)cs.nextElement(); - Certificate cert = engineGetCertificate(name); - boolean cAttrSet = false; - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(name)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); - } - - // - // make sure we have a local key-id - // - if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) - { - bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(cert.getPublicKey())); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - - cAttrSet = true; - } - } - - if (!cAttrSet) - { - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_localKeyId); - fSeq.add(new DERSet(createSubjectKeyId(cert.getPublicKey()))); - fName.add(new DERSequence(fSeq)); - - fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_friendlyName); - fSeq.add(new DERSet(new DERBMPString(name))); - - fName.add(new DERSequence(fSeq)); - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); - - certSeq.add(sBag); - - doneCerts.put(cert, cert); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - cs = certs.keys(); - while (cs.hasMoreElements()) - { - try - { - String certId = (String)cs.nextElement(); - Certificate cert = (Certificate)certs.get(certId); - boolean cAttrSet = false; - - if (keys.get(certId) != null) - { - continue; - } - - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(certId)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(certId)); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - - // a certificate not immediately linked to a key doesn't require - // a localKeyID and will confuse some PKCS12 implementations. - // - // If we find one, we'll prune it out. - if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) - { - continue; - } - - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - - cAttrSet = true; - } - } - - if (!cAttrSet) - { - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_friendlyName); - fSeq.add(new DERSet(new DERBMPString(certId))); - - fName.add(new DERSequence(fSeq)); - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); - - certSeq.add(sBag); - - doneCerts.put(cert, cert); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - cs = chainCerts.keys(); - while (cs.hasMoreElements()) - { - try - { - CertId certId = (CertId)cs.nextElement(); - Certificate cert = (Certificate)chainCerts.get(certId); - - if (doneCerts.get(cert) != null) - { - continue; - } - - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - - // a certificate not immediately linked to a key doesn't require - // a localKeyID and will confuse some PKCS12 implementations. - // - // If we find one, we'll prune it out. - if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) - { - continue; - } - - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - } - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Primitive(), new DERSet(fName)); - - certSeq.add(sBag); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - byte[] certSeqEncoded = new DERSequence(certSeq).getEncoded(ASN1Encoding.DER); - byte[] certBytes = cryptData(true, cAlgId, password, false, certSeqEncoded); - EncryptedData cInfo = new EncryptedData(data, cAlgId, new BERConstructedOctetString(certBytes)); - - ContentInfo[] info = new ContentInfo[] - { - new ContentInfo(data, keyString), - new ContentInfo(encryptedData, cInfo.toASN1Primitive()) - }; - - AuthenticatedSafe auth = new AuthenticatedSafe(info); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - DEROutputStream asn1Out; - if (useDEREncoding) - { - asn1Out = new DEROutputStream(bOut); - } - else - { - asn1Out = new BEROutputStream(bOut); - } - - asn1Out.writeObject(auth); - - byte[] pkg = bOut.toByteArray(); - - ContentInfo mainInfo = new ContentInfo(data, new BERConstructedOctetString(pkg)); - - // - // create the mac - // - byte[] mSalt = new byte[20]; - int itCount = MIN_ITERATIONS; - - random.nextBytes(mSalt); - - byte[] data = ((ASN1OctetString)mainInfo.getContent()).getOctets(); - - MacData mData; - - try - { - byte[] res = calculatePbeMac(id_SHA1, mSalt, itCount, password, false, data); - - AlgorithmIdentifier algId = new AlgorithmIdentifier(id_SHA1, new DERNull()); - DigestInfo dInfo = new DigestInfo(algId, res); - - mData = new MacData(dInfo, mSalt, itCount); - } - catch (Exception e) - { - throw new IOException("error constructing MAC: " + e.toString()); - } - - // - // output the Pfx - // - Pfx pfx = new Pfx(mainInfo, mData); - - if (useDEREncoding) - { - asn1Out = new DEROutputStream(stream); - } - else - { - asn1Out = new BEROutputStream(stream); - } - - asn1Out.writeObject(pfx); - } - - private static byte[] calculatePbeMac( - ASN1ObjectIdentifier oid, - byte[] salt, - int itCount, - char[] password, - boolean wrongPkcs12Zero, - byte[] data) - throws Exception - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(oid.getId(), bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec); - key.setTryWrongPKCS12Zero(wrongPkcs12Zero); - - Mac mac = Mac.getInstance(oid.getId(), bcProvider); - mac.init(key, defParams); - mac.update(data); - return mac.doFinal(); - } - - public static class BCPKCS12KeyStore - extends JDKPKCS12KeyStore - { - public BCPKCS12KeyStore() - { - super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); - } - } - - public static class BCPKCS12KeyStore3DES - extends JDKPKCS12KeyStore - { - public BCPKCS12KeyStore3DES() - { - super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); - } - } - - public static class DefPKCS12KeyStore - extends JDKPKCS12KeyStore - { - public DefPKCS12KeyStore() - { - super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); - } - } - - public static class DefPKCS12KeyStore3DES - extends JDKPKCS12KeyStore - { - public DefPKCS12KeyStore3DES() - { - super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); - } - } - - private static class IgnoresCaseHashtable - { - private Hashtable orig = new Hashtable(); - private Hashtable keys = new Hashtable(); - - public void put(String key, Object value) - { - String lower = Strings.toLowerCase(key); - String k = (String)keys.get(lower); - if (k != null) - { - orig.remove(k); - } - - keys.put(lower, key); - orig.put(key, value); - } - - public Enumeration keys() - { - return orig.keys(); - } - - public Object remove(String alias) - { - String k = (String)keys.remove(Strings.toLowerCase(alias)); - if (k == null) - { - return null; - } - - return orig.remove(k); - } - - public Object get(String alias) - { - String k = (String)keys.get(Strings.toLowerCase(alias)); - if (k == null) - { - return null; - } - - return orig.get(k); - } - - public Enumeration elements() - { - return orig.elements(); - } - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java index 4dc75cf31..989d9c9a6 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/PKIXCertPathValidatorSpi.java @@ -21,7 +21,7 @@ import java.util.Set; import org.spongycastle.jce.X509Principal; import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.jce.exception.ExtCertPathValidatorException; import org.spongycastle.x509.ExtendedPKIXParameters; @@ -218,7 +218,7 @@ public class PKIXCertPathValidatorSpi throw new ExtCertPathValidatorException( "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1); } - DERObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId(); + ASN1ObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.getObjectId(); ASN1Encodable workingPublicKeyParameters = workingAlgId.getParameters(); // diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java index 17efca7ec..3f37d4c96 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/RFC3280CertPathUtilities.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.PublicKey; +import java.text.SimpleDateFormat; import org.spongycastle.jce.cert.CertPath; import org.spongycastle.jce.cert.CertPathBuilder; import org.spongycastle.jce.cert.CertPathBuilderException; @@ -34,8 +35,8 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.ASN1TaggedObject; -import org.spongycastle.asn1.DERInteger; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.BasicConstraints; import org.spongycastle.asn1.x509.CRLDistPoint; @@ -905,8 +906,8 @@ public class RFC3280CertPathUtilities for (int j = 0; j < mappings.size(); j++) { ASN1Sequence mapping = (ASN1Sequence)mappings.getObjectAt(j); - String id_p = ((DERObjectIdentifier)mapping.getObjectAt(0)).getId(); - String sd_p = ((DERObjectIdentifier)mapping.getObjectAt(1)).getId(); + String id_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(0)).getId(); + String sd_p = ((ASN1ObjectIdentifier)mapping.getObjectAt(1)).getId(); Set tmp; if (!m_idp.containsKey(id_p)) @@ -1084,14 +1085,14 @@ public class RFC3280CertPathUtilities for (int j = 0; j < mappings.size(); j++) { - DERObjectIdentifier issuerDomainPolicy = null; - DERObjectIdentifier subjectDomainPolicy = null; + ASN1ObjectIdentifier issuerDomainPolicy = null; + ASN1ObjectIdentifier subjectDomainPolicy = null; try { ASN1Sequence mapping = DERSequence.getInstance(mappings.getObjectAt(j)); - issuerDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(0)); - subjectDomainPolicy = DERObjectIdentifier.getInstance(mapping.getObjectAt(1)); + issuerDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(0)); + subjectDomainPolicy = ASN1ObjectIdentifier.getInstance(mapping.getObjectAt(1)); } catch (Exception e) { @@ -1298,7 +1299,7 @@ public class RFC3280CertPathUtilities while (e.hasMoreElements()) { PolicyInformation pInfo = PolicyInformation.getInstance(e.nextElement()); - DERObjectIdentifier pOid = pInfo.getPolicyIdentifier(); + ASN1ObjectIdentifier pOid = pInfo.getPolicyIdentifier(); pols.add(pOid.getId()); @@ -1377,9 +1378,9 @@ public class RFC3280CertPathUtilities { _policy = (String)_tmp; } - else if (_tmp instanceof DERObjectIdentifier) + else if (_tmp instanceof ASN1ObjectIdentifier) { - _policy = ((DERObjectIdentifier)_tmp).getId(); + _policy = ((ASN1ObjectIdentifier)_tmp).getId(); } else { @@ -1579,7 +1580,7 @@ public class RFC3280CertPathUtilities ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement()); if (constraint.getTagNo() == 0) { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < explicitPolicy) { return tmpInt; @@ -1633,7 +1634,7 @@ public class RFC3280CertPathUtilities ASN1TaggedObject constraint = ASN1TaggedObject.getInstance(policyConstraints.nextElement()); if (constraint.getTagNo() == 1) { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); if (tmpInt < policyMapping) { return tmpInt; @@ -2018,7 +2019,7 @@ public class RFC3280CertPathUtilities } if (certStatus.getCertStatus() != CertStatus.UNREVOKED) { - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss +0000"); df.setTimeZone(TimeZone.getTimeZone("UTC")); String message = "Certificate revocation after " + df.format(certStatus.getRevocationDate()); message += ", reason: " + crlReasons[certStatus.getCertStatus()]; @@ -2045,10 +2046,10 @@ public class RFC3280CertPathUtilities // // (j) // - DERInteger iap = null; + ASN1Integer iap = null; try { - iap = DERInteger.getInstance(CertPathValidatorUtilities.getExtensionValue(cert, + iap = ASN1Integer.getInstance(CertPathValidatorUtilities.getExtensionValue(cert, RFC3280CertPathUtilities.INHIBIT_ANY_POLICY)); } catch (Exception e) @@ -2351,7 +2352,7 @@ public class RFC3280CertPathUtilities case 0: try { - tmpInt = DERInteger.getInstance(constraint, false).getValue().intValue(); + tmpInt = ASN1Integer.getInstance(constraint, false).getValue().intValue(); } catch (Exception e) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLEntryObject.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLEntryObject.java index cbbc098af..dd0a32c96 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLEntryObject.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLEntryObject.java @@ -12,7 +12,7 @@ import java.util.Set; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DEREnumerated; +import org.spongycastle.asn1.ASN1Enumerated; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.CRLReason; @@ -262,7 +262,7 @@ public class X509CRLEntryObject extends X509CRLEntry { if (oid.equals(X509Extension.reasonCode)) { - buf.append(CRLReason.getInstance(DEREnumerated.getInstance(dIn.readObject()))).append(nl); + buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl); } else if (oid.equals(X509Extension.certificateIssuer)) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLObject.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLObject.java index ce0de272b..46f9dab5b 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLObject.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/jce/provider/X509CRLObject.java @@ -26,7 +26,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.util.ASN1Dump; import org.spongycastle.asn1.x500.X500Name; import org.spongycastle.asn1.x509.CRLDistPoint; @@ -432,7 +432,7 @@ public class X509CRLObject if (oid.equals(Extension.cRLNumber)) { buf.append( - new CRLNumber(DERInteger.getInstance( + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } @@ -440,7 +440,7 @@ public class X509CRLObject { buf.append( "Base CRL: " - + new CRLNumber(DERInteger.getInstance( + + new CRLNumber(ASN1Integer.getInstance( dIn.readObject()).getPositiveValue())) .append(nl); } diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/BasicOCSPResp.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/BasicOCSPResp.java deleted file mode 100644 index 1e64236ff..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/BasicOCSPResp.java +++ /dev/null @@ -1,366 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Signature; -import org.spongycastle.jce.cert.CertStore; -import org.spongycastle.jce.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import org.spongycastle.jce.cert.CertificateFactory; -import org.spongycastle.jce.cert.CollectionCertStoreParameters; -import java.security.cert.X509Certificate; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.ocsp.BasicOCSPResponse; -import org.spongycastle.asn1.ocsp.ResponseData; -import org.spongycastle.asn1.ocsp.SingleResponse; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; - -/** - *- * BasicOCSPResponse ::= SEQUENCE { - * tbsResponseData ResponseData, - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } - *- * - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class BasicOCSPResp - implements java.security.cert.X509Extension -{ - BasicOCSPResponse resp; - ResponseData data; - X509Certificate[] chain = null; - - public BasicOCSPResp( - BasicOCSPResponse resp) - { - this.resp = resp; - this.data = resp.getTbsResponseData(); - } - - /** - * Return the DER encoding of the tbsResponseData field. - * @return DER encoding of tbsResponseData - * @throws OCSPException in the event of an encoding error. - */ - public byte[] getTBSResponseData() - throws OCSPException - { - try - { - return resp.getTbsResponseData().getEncoded(); - } - catch (IOException e) - { - throw new OCSPException("problem encoding tbsResponseData", e); - } - } - - public int getVersion() - { - return data.getVersion().getValue().intValue() + 1; - } - - public RespID getResponderId() - { - return new RespID(data.getResponderID()); - } - - public Date getProducedAt() - { - try - { - return data.getProducedAt().getDate(); - } - catch (ParseException e) - { - throw new IllegalStateException("ParseException:" + e.getMessage()); - } - } - - public SingleResp[] getResponses() - { - ASN1Sequence s = data.getResponses(); - SingleResp[] rs = new SingleResp[s.size()]; - - for (int i = 0; i != rs.length; i++) - { - rs[i] = new SingleResp(SingleResponse.getInstance(s.getObjectAt(i))); - } - - return rs; - } - - public X509Extensions getResponseExtensions() - { - return X509Extensions.getInstance(data.getResponseExtensions()); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getResponseExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getResponseExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } - - public String getSignatureAlgName() - { - return OCSPUtil.getAlgorithmName(resp.getSignatureAlgorithm().getObjectId()); - } - - public String getSignatureAlgOID() - { - return resp.getSignatureAlgorithm().getObjectId().getId(); - } - - /** - * @deprecated RespData class is no longer required as all functionality is - * available on this class. - * @return the RespData object - */ - public RespData getResponseData() - { - return new RespData(resp.getTbsResponseData()); - } - - public byte[] getSignature() - { - return resp.getSignature().getBytes(); - } - - private List getCertList( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = new ArrayList(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - CertificateFactory cf; - - try - { - cf = OCSPUtil.createX509CertificateFactory(provider); - } - catch (CertificateException ex) - { - throw new OCSPException("can't get certificate factory.", ex); - } - - // - // load the certificates and revocation lists if we have any - // - ASN1Sequence s = resp.getCerts(); - - if (s != null) - { - Enumeration e = s.getObjects(); - - while (e.hasMoreElements()) - { - try - { - aOut.writeObject((ASN1Encodable)e.nextElement()); - - certs.add(cf.generateCertificate( - new ByteArrayInputStream(bOut.toByteArray()))); - } - catch (IOException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - catch (CertificateException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - - bOut.reset(); - } - } - - return certs; - } - - public X509Certificate[] getCerts( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = getCertList(provider); - - return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); - } - - /** - * Return the certificates, if any associated with the response. - * @param type type of CertStore to create - * @param provider provider to use - * @return a CertStore, possibly empty - * @throws NoSuchAlgorithmException - * @throws NoSuchProviderException - * @throws OCSPException - */ - public CertStore getCertificates( - String type, - String provider) - throws NoSuchAlgorithmException, NoSuchProviderException, OCSPException - { - try - { - CertStoreParameters params = new CollectionCertStoreParameters(this.getCertList(provider)); - return OCSPUtil.createCertStoreInstance(type, params, provider); - } - catch (InvalidAlgorithmParameterException e) - { - throw new OCSPException("can't setup the CertStore", e); - } - } - - /** - * verify the signature against the tbsResponseData object we contain. - */ - public boolean verify( - PublicKey key, - String sigProvider) - throws OCSPException, NoSuchProviderException - { - try - { - Signature signature = OCSPUtil.createSignatureInstance(this.getSignatureAlgName(), sigProvider); - - signature.initVerify(key); - - signature.update(resp.getTbsResponseData().getEncoded(ASN1Encoding.DER)); - - return signature.verify(this.getSignature()); - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (Exception e) - { - throw new OCSPException("exception processing sig: " + e, e); - } - } - - /** - * return the ASN.1 encoded representation of this object. - */ - public byte[] getEncoded() - throws IOException - { - return resp.getEncoded(); - } - - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - - if (!(o instanceof BasicOCSPResp)) - { - return false; - } - - BasicOCSPResp r = (BasicOCSPResp)o; - - return resp.equals(r.resp); - } - - public int hashCode() - { - return resp.hashCode(); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReq.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReq.java deleted file mode 100644 index 7f4a091f0..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReq.java +++ /dev/null @@ -1,415 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1Encoding; -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.ocsp.OCSPRequest; -import org.spongycastle.asn1.ocsp.Request; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.asn1.x509.X509Extension; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.jce.cert.CertStore; -import org.spongycastle.jce.cert.CertStoreParameters; -import org.spongycastle.jce.cert.CertificateFactory; -import org.spongycastle.jce.cert.CollectionCertStoreParameters; - -/** - *- * OCSPRequest ::= SEQUENCE { - * tbsRequest TBSRequest, - * optionalSignature [0] EXPLICIT Signature OPTIONAL } - * - * TBSRequest ::= SEQUENCE { - * version [0] EXPLICIT Version DEFAULT v1, - * requestorName [1] EXPLICIT GeneralName OPTIONAL, - * requestList SEQUENCE OF Request, - * requestExtensions [2] EXPLICIT Extensions OPTIONAL } - * - * Signature ::= SEQUENCE { - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING, - * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} - * - * Version ::= INTEGER { v1(0) } - * - * Request ::= SEQUENCE { - * reqCert CertID, - * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } - * - * CertID ::= SEQUENCE { - * hashAlgorithm AlgorithmIdentifier, - * issuerNameHash OCTET STRING, -- Hash of Issuer's DN - * issuerKeyHash OCTET STRING, -- Hash of Issuers public key - * serialNumber CertificateSerialNumber } - *- */ -public class OCSPReq - implements java.security.cert.X509Extension -{ - private OCSPRequest req; - - public OCSPReq( - OCSPRequest req) - { - this.req = req; - } - - public OCSPReq( - byte[] req) - throws IOException - { - this(new ASN1InputStream(req)); - } - - public OCSPReq( - InputStream in) - throws IOException - { - this(new ASN1InputStream(in)); - } - - private OCSPReq( - ASN1InputStream aIn) - throws IOException - { - try - { - this.req = OCSPRequest.getInstance(aIn.readObject()); - } - catch (IllegalArgumentException e) - { - throw new IOException("malformed request: " + e.getMessage()); - } - catch (ClassCastException e) - { - throw new IOException("malformed request: " + e.getMessage()); - } - } - - /** - * Return the DER encoding of the tbsRequest field. - * @return DER encoding of tbsRequest - * @throws OCSPException in the event of an encoding error. - */ - public byte[] getTBSRequest() - throws OCSPException - { - try - { - return req.getTbsRequest().getEncoded(); - } - catch (IOException e) - { - throw new OCSPException("problem encoding tbsRequest", e); - } - } - - public int getVersion() - { - return req.getTbsRequest().getVersion().getValue().intValue() + 1; - } - - public GeneralName getRequestorName() - { - return GeneralName.getInstance(req.getTbsRequest().getRequestorName()); - } - - public Req[] getRequestList() - { - ASN1Sequence seq = req.getTbsRequest().getRequestList(); - Req[] requests = new Req[seq.size()]; - - for (int i = 0; i != requests.length; i++) - { - requests[i] = new Req(Request.getInstance(seq.getObjectAt(i))); - } - - return requests; - } - - public X509Extensions getRequestExtensions() - { - return X509Extensions.getInstance(req.getTbsRequest().getRequestExtensions()); - } - - /** - * return the object identifier representing the signature algorithm - */ - public String getSignatureAlgOID() - { - if (!this.isSigned()) - { - return null; - } - - return req.getOptionalSignature().getSignatureAlgorithm().getObjectId().getId(); - } - - public byte[] getSignature() - { - if (!this.isSigned()) - { - return null; - } - - return req.getOptionalSignature().getSignature().getBytes(); - } - - private List getCertList( - String provider) - throws OCSPException, NoSuchProviderException - { - List certs = new ArrayList(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - CertificateFactory cf; - - try - { - cf = OCSPUtil.createX509CertificateFactory(provider); - } - catch (CertificateException ex) - { - throw new OCSPException("can't get certificate factory.", ex); - } - - // - // load the certificates if we have any - // - ASN1Sequence s = req.getOptionalSignature().getCerts(); - - if (s != null) - { - Enumeration e = s.getObjects(); - - while (e.hasMoreElements()) - { - try - { - aOut.writeObject((ASN1Encodable)e.nextElement()); - - certs.add(cf.generateCertificate( - new ByteArrayInputStream(bOut.toByteArray()))); - } - catch (IOException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - catch (CertificateException ex) - { - throw new OCSPException( - "can't re-encode certificate!", ex); - } - - bOut.reset(); - } - } - - return certs; - } - - public X509Certificate[] getCerts( - String provider) - throws OCSPException, NoSuchProviderException - { - if (!this.isSigned()) - { - return null; - } - - List certs = this.getCertList(provider); - - return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); - } - - /** - * If the request is signed return a possibly empty CertStore containing the certificates in the - * request. If the request is not signed the method returns null. - * - * @param type type of CertStore to return - * @param provider provider to use - * @return null if not signed, a CertStore otherwise - * @throws NoSuchAlgorithmException - * @throws NoSuchProviderException - * @throws OCSPException - */ - public CertStore getCertificates( - String type, - String provider) - throws NoSuchAlgorithmException, NoSuchProviderException, OCSPException - { - if (!this.isSigned()) - { - return null; - } - - try - { - CertStoreParameters params = new CollectionCertStoreParameters(this.getCertList(provider)); - return OCSPUtil.createCertStoreInstance(type, params, provider); - } - catch (InvalidAlgorithmParameterException e) - { - throw new OCSPException("can't setup the CertStore", e); - } - } - - /** - * Return whether or not this request is signed. - * - * @return true if signed false otherwise. - */ - public boolean isSigned() - { - return req.getOptionalSignature() != null; - } - - /** - * verify the signature against the TBSRequest object we contain. - */ - public boolean verify( - PublicKey key, - String sigProvider) - throws OCSPException, NoSuchProviderException - { - if (!this.isSigned()) - { - throw new OCSPException("attempt to verify signature on unsigned object"); - } - - try - { - Signature signature = OCSPUtil.createSignatureInstance(this.getSignatureAlgOID(), sigProvider); - - signature.initVerify(key); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(req.getTbsRequest()); - - signature.update(bOut.toByteArray()); - - return signature.verify(this.getSignature()); - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (Exception e) - { - throw new OCSPException("exception processing sig: " + e, e); - } - } - - /** - * return the ASN.1 encoded representation of this object. - */ - public byte[] getEncoded() - throws IOException - { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(req); - - return bOut.toByteArray(); - } - - /** - * RFC 2650 doesn't specify any critical extensions so we return true - * if any are encountered. - * - * @return true if any critical extensions are present. - */ - public boolean hasUnsupportedCriticalExtension() - { - Set extns = getCriticalExtensionOIDs(); - if (extns != null && !extns.isEmpty()) - { - return true; - } - - return false; - } - - private Set getExtensionOIDs(boolean critical) - { - Set set = new HashSet(); - X509Extensions extensions = this.getRequestExtensions(); - - if (extensions != null) - { - Enumeration e = extensions.oids(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - X509Extension ext = extensions.getExtension(oid); - - if (critical == ext.isCritical()) - { - set.add(oid.getId()); - } - } - } - - return set; - } - - public Set getCriticalExtensionOIDs() - { - return getExtensionOIDs(true); - } - - public Set getNonCriticalExtensionOIDs() - { - return getExtensionOIDs(false); - } - - public byte[] getExtensionValue(String oid) - { - X509Extensions exts = this.getRequestExtensions(); - - if (exts != null) - { - X509Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); - - if (ext != null) - { - try - { - return ext.getValue().getEncoded(ASN1Encoding.DER); - } - catch (Exception e) - { - throw new RuntimeException("error encoding " + e.toString()); - } - } - } - - return null; - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReqGenerator.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReqGenerator.java deleted file mode 100644 index 755751fb6..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPReqGenerator.java +++ /dev/null @@ -1,292 +0,0 @@ -package org.spongycastle.ocsp; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.SecureRandom; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1OutputStream; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.ocsp.OCSPRequest; -import org.spongycastle.asn1.ocsp.Request; -import org.spongycastle.asn1.ocsp.Signature; -import org.spongycastle.asn1.ocsp.TBSRequest; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.Extensions; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.asn1.x509.X509CertificateStructure; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.jce.X509Principal; - -/** - * @deprecated use classes in org.spongycastle.cert.ocsp. - */ -public class OCSPReqGenerator -{ - private List list = new ArrayList(); - private GeneralName requestorName = null; - private X509Extensions requestExtensions = null; - - private class RequestObject - { - CertificateID certId; - X509Extensions extensions; - - public RequestObject( - CertificateID certId, - X509Extensions extensions) - { - this.certId = certId; - this.extensions = extensions; - } - - public Request toRequest() - throws Exception - { - return new Request(certId.toASN1Object(), Extensions.getInstance(extensions)); - } - } - - /** - * Add a request for the given CertificateID. - * - * @param certId certificate ID of interest - */ - public void addRequest( - CertificateID certId) - { - list.add(new RequestObject(certId, null)); - } - - /** - * Add a request with extensions - * - * @param certId certificate ID of interest - * @param singleRequestExtensions the extensions to attach to the request - */ - public void addRequest( - CertificateID certId, - X509Extensions singleRequestExtensions) - { - list.add(new RequestObject(certId, singleRequestExtensions)); - } - - /** - * Set the requestor name to the passed in X500Principal - * - * @param requestorName a X500Principal representing the requestor name. - */ - public void setRequestorName( - X509Principal requestorName) - { - try - { - this.requestorName = new GeneralName(GeneralName.directoryName, new X509Principal(requestorName.getEncoded())); - } - catch (IOException e) - { - throw new IllegalArgumentException("cannot encode principal: " + e); - } - } - - public void setRequestorName( - GeneralName requestorName) - { - this.requestorName = requestorName; - } - - public void setRequestExtensions( - X509Extensions requestExtensions) - { - this.requestExtensions = requestExtensions; - } - - private OCSPReq generateRequest( - DERObjectIdentifier signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException - { - Iterator it = list.iterator(); - - ASN1EncodableVector requests = new ASN1EncodableVector(); - - while (it.hasNext()) - { - try - { - requests.add(((RequestObject)it.next()).toRequest()); - } - catch (Exception e) - { - throw new OCSPException("exception creating Request", e); - } - } - - TBSRequest tbsReq = new TBSRequest(requestorName, new DERSequence(requests), requestExtensions); - - java.security.Signature sig = null; - Signature signature = null; - - if (signingAlgorithm != null) - { - if (requestorName == null) - { - throw new OCSPException("requestorName must be specified if request is signed."); - } - - try - { - sig = OCSPUtil.createSignatureInstance(signingAlgorithm.getId(), provider); - if (random != null) - { - sig.initSign(key, random); - } - else - { - sig.initSign(key); - } - } - catch (NoSuchProviderException e) - { - // TODO Why this special case? - throw e; - } - catch (GeneralSecurityException e) - { - throw new OCSPException("exception creating signature: " + e, e); - } - - DERBitString bitSig = null; - - try - { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream aOut = new ASN1OutputStream(bOut); - - aOut.writeObject(tbsReq); - - sig.update(bOut.toByteArray()); - - bitSig = new DERBitString(sig.sign()); - } - catch (Exception e) - { - throw new OCSPException("exception processing TBSRequest: " + e, e); - } - - AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, new DERNull()); - - if (chain != null && chain.length > 0) - { - ASN1EncodableVector v = new ASN1EncodableVector(); - try - { - for (int i = 0; i != chain.length; i++) - { - v.add(new X509CertificateStructure( - (ASN1Sequence)ASN1Primitive.fromByteArray(chain[i].getEncoded()))); - } - } - catch (IOException e) - { - throw new OCSPException("error processing certs", e); - } - catch (CertificateEncodingException e) - { - throw new OCSPException("error encoding certs", e); - } - - signature = new Signature(sigAlgId, bitSig, new DERSequence(v)); - } - else - { - signature = new Signature(sigAlgId, bitSig); - } - } - - return new OCSPReq(new OCSPRequest(tbsReq, signature)); - } - - /** - * Generate an unsigned request - * - * @return the OCSPReq - * @throws OCSPException - */ - public OCSPReq generate() - throws OCSPException - { - try - { - return generateRequest(null, null, null, null, null); - } - catch (NoSuchProviderException e) - { - // - // this shouldn't happen but... - // - throw new OCSPException("no provider! - " + e, e); - } - } - - public OCSPReq generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - return generate(signingAlgorithm, key, chain, provider, null); - } - - public OCSPReq generate( - String signingAlgorithm, - PrivateKey key, - X509Certificate[] chain, - String provider, - SecureRandom random) - throws OCSPException, NoSuchProviderException, IllegalArgumentException - { - if (signingAlgorithm == null) - { - throw new IllegalArgumentException("no signing algorithm specified"); - } - - try - { - DERObjectIdentifier oid = OCSPUtil.getAlgorithmOID(signingAlgorithm); - - return generateRequest(oid, key, chain, provider, random); - } - catch (IllegalArgumentException e) - { - throw new IllegalArgumentException("unknown signing algorithm specified: " + signingAlgorithm); - } - } - - /** - * Return an iterator of the signature names supported by the generator. - * - * @return an iterator containing recognised names. - */ - public Iterator getSignatureAlgNames() - { - return OCSPUtil.getAlgNames(); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPUtil.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPUtil.java deleted file mode 100644 index ddcadda32..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/OCSPUtil.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.spongycastle.ocsp; - -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; -import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; -import org.spongycastle.asn1.nist.NISTObjectIdentifiers; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x9.X9ObjectIdentifiers; -import org.spongycastle.util.Strings; - -import java.security.InvalidAlgorithmParameterException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Signature; -import org.spongycastle.jce.cert.CertStore; -import org.spongycastle.jce.cert.CertStoreParameters; -import java.security.cert.CertificateException; -import org.spongycastle.jce.cert.CertificateFactory; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -class OCSPUtil -{ - private static Hashtable algorithms = new Hashtable(); - private static Hashtable oids = new Hashtable(); - private static Set noParams = new HashSet(); - - static - { - algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption); - algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption); - algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption); - algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption); - algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption); - algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption); - algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption); - algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1); - algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224); - algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256); - algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1); - algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); - algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); - algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); - algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); - algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); - - oids.put(PKCSObjectIdentifiers.md2WithRSAEncryption, "MD2WITHRSA"); - oids.put(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA"); - oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160, "RIPEMD160WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128, "RIPEMD128WITHRSA"); - oids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256, "RIPEMD256WITHRSA"); - oids.put(X9ObjectIdentifiers.id_dsa_with_sha1, "SHA1WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha224, "SHA224WITHDSA"); - oids.put(NISTObjectIdentifiers.dsa_with_sha256, "SHA256WITHDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384WITHECDSA"); - oids.put(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512WITHECDSA"); - oids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, "GOST3411WITHGOST3410"); - - // - // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. - // The parameters field SHALL be NULL for RSA based signature algorithms. - // - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384); - noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512); - noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1); - noParams.add(NISTObjectIdentifiers.dsa_with_sha224); - noParams.add(NISTObjectIdentifiers.dsa_with_sha256); - } - - static DERObjectIdentifier getAlgorithmOID( - String algorithmName) - { - algorithmName = Strings.toUpperCase(algorithmName); - - if (algorithms.containsKey(algorithmName)) - { - return (DERObjectIdentifier)algorithms.get(algorithmName); - } - - return new DERObjectIdentifier(algorithmName); - } - - static String getAlgorithmName( - DERObjectIdentifier oid) - { - if (oids.containsKey(oid)) - { - return (String)oids.get(oid); - } - - return oid.getId(); - } - - static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid) - { - if (noParams.contains(sigOid)) - { - return new AlgorithmIdentifier(sigOid); - } - else - { - return new AlgorithmIdentifier(sigOid, new DERNull()); - } - } - - static Iterator getAlgNames() - { - Enumeration e = algorithms.keys(); - List l = new ArrayList(); - - while (e.hasMoreElements()) - { - l.add(e.nextElement()); - } - - return l.iterator(); - } - - static CertStore createCertStoreInstance(String type, CertStoreParameters params, String provider) - throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return CertStore.getInstance(type, params); - } - - return CertStore.getInstance(type, params, provider); - } - - static MessageDigest createDigestInstance(String digestName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return MessageDigest.getInstance(digestName); - } - - return MessageDigest.getInstance(digestName, provider); - } - - static Signature createSignatureInstance(String sigName, String provider) - throws NoSuchAlgorithmException, NoSuchProviderException - { - if (provider == null) - { - return Signature.getInstance(sigName); - } - - return Signature.getInstance(sigName, provider); - } - - static CertificateFactory createX509CertificateFactory(String provider) - throws CertificateException, NoSuchProviderException - { - if (provider == null) - { - return CertificateFactory.getInstance("X.509"); - } - - return CertificateFactory.getInstance("X.509", provider); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/RespID.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/RespID.java deleted file mode 100644 index 8a491d046..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/ocsp/RespID.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.spongycastle.ocsp; - -import java.security.MessageDigest; -import java.security.PublicKey; - -import org.spongycastle.jce.X509Principal; - -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.ocsp.ResponderID; -import org.spongycastle.asn1.x500.X500Name; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; - -/** - * Carrier for a ResponderID. - */ -public class RespID -{ - ResponderID id; - - public RespID( - ResponderID id) - { - this.id = id; - } - - public RespID( - X509Principal name) - { - this.id = new ResponderID(X500Name.getInstance(name.getEncoded())); - } - - public RespID( - PublicKey key) - throws OCSPException - { - try - { - // TODO Allow specification of a particular provider - MessageDigest digest = OCSPUtil.createDigestInstance("SHA1", null); - - ASN1InputStream aIn = new ASN1InputStream(key.getEncoded()); - SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject()); - - digest.update(info.getPublicKeyData().getBytes()); - - ASN1OctetString keyHash = new DEROctetString(digest.digest()); - - this.id = new ResponderID(keyHash); - } - catch (Exception e) - { - throw new OCSPException("problem creating ID: " + e, e); - } - } - - public ResponderID toASN1Object() - { - return id; - } - - public boolean equals( - Object o) - { - if (!(o instanceof RespID)) - { - return false; - } - - RespID obj = (RespID)o; - - return id.equals(obj.id); - } - - public int hashCode() - { - return id.hashCode(); - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java index bb8cf600c..554911f0f 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509CRLStoreSelector.java @@ -1,6 +1,6 @@ package org.spongycastle.x509; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.x509.X509Extensions; import org.spongycastle.util.Arrays; import org.spongycastle.util.Selector; @@ -96,14 +96,14 @@ public class X509CRLStoreSelector return false; } X509CRL crl = (X509CRL)obj; - DERInteger dci = null; + ASN1Integer dci = null; try { byte[] bytes = crl .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); if (bytes != null) { - dci = DERInteger.getInstance(X509ExtensionUtil + dci = ASN1Integer.getInstance(X509ExtensionUtil .fromExtensionValue(bytes)); } } diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java index 3b249ac8f..93ec8b638 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509Util.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -134,21 +134,21 @@ class X509Util new ASN1Integer(1)); } - static DERObjectIdentifier getAlgorithmOID( + static ASN1ObjectIdentifier getAlgorithmOID( String algorithmName) { algorithmName = Strings.toUpperCase(algorithmName); if (algorithms.containsKey(algorithmName)) { - return (DERObjectIdentifier)algorithms.get(algorithmName); + return (ASN1ObjectIdentifier)algorithms.get(algorithmName); } - return new DERObjectIdentifier(algorithmName); + return new ASN1ObjectIdentifier(algorithmName); } static AlgorithmIdentifier getSigAlgID( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String algorithmName) { if (noParams.contains(sigOid)) @@ -204,7 +204,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, PrivateKey key, SecureRandom random, @@ -235,7 +235,7 @@ class X509Util } static byte[] calculateSignature( - DERObjectIdentifier sigOid, + ASN1ObjectIdentifier sigOid, String sigName, String provider, PrivateKey key, diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java index 40e2d4272..d038b5cfd 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V1CertificateGenerator.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; @@ -40,7 +40,7 @@ import org.spongycastle.jce.provider.X509CertificateObject; public class X509V1CertificateGenerator { private V1TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java index 5b1c8e4f9..8da36afb8 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V2CRLGenerator.java @@ -24,7 +24,6 @@ import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.CertificateList; @@ -35,7 +34,6 @@ import org.spongycastle.asn1.x509.V2TBSCertListGenerator; import org.spongycastle.asn1.x509.X509Extensions; import org.spongycastle.asn1.x509.X509ExtensionsGenerator; import org.spongycastle.asn1.x509.X509Name; -import org.spongycastle.jce.X509Principal; import org.spongycastle.jce.provider.X509CRLObject; /** @@ -45,7 +43,7 @@ import org.spongycastle.jce.provider.X509CRLObject; public class X509V2CRLGenerator { private V2TBSCertListGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -178,14 +176,14 @@ public class X509V2CRLGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -200,14 +198,14 @@ public class X509V2CRLGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 0) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java index 716e5dd23..e58310e2a 100644 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java +++ b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/X509V3CertificateGenerator.java @@ -22,7 +22,7 @@ import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERBitString; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; @@ -42,7 +42,7 @@ import org.spongycastle.x509.extension.X509ExtensionUtil; public class X509V3CertificateGenerator { private V3TBSCertificateGenerator tbsGen; - private DERObjectIdentifier sigOID; + private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; @@ -192,14 +192,14 @@ public class X509V3CertificateGenerator boolean critical, ASN1Encodable value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value) { @@ -216,14 +216,14 @@ public class X509V3CertificateGenerator boolean critical, byte[] value) { - this.addExtension(new DERObjectIdentifier(oid), critical, value); + this.addExtension(new ASN1ObjectIdentifier(oid), critical, value); } /** * add a given extension field for the standard extensions tag (tag 3) */ public void addExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, byte[] value) { @@ -266,7 +266,7 @@ public class X509V3CertificateGenerator * @throws CertificateParsingException if the extension cannot be extracted. */ public void copyAndAddExtension( - DERObjectIdentifier oid, + ASN1ObjectIdentifier oid, boolean critical, X509Certificate cert) throws CertificateParsingException diff --git a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/examples/AttrCertExample.java b/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/examples/AttrCertExample.java deleted file mode 100644 index 8e9a5ec05..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.3/org/spongycastle/x509/examples/AttrCertExample.java +++ /dev/null @@ -1,290 +0,0 @@ -package org.spongycastle.x509.examples; - -import java.security.cert.*; -import java.security.spec.RSAPrivateCrtKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.security.*; -import java.math.*; -import java.util.Date; -import java.util.Hashtable; -import java.util.Vector; - -import org.spongycastle.jce.PrincipalUtil; -import org.spongycastle.jce.X509Principal; -import org.spongycastle.jce.provider.*; -import org.spongycastle.asn1.*; -import org.spongycastle.asn1.misc.MiscObjectIdentifiers; -import org.spongycastle.asn1.misc.NetscapeCertType; -import org.spongycastle.asn1.x509.GeneralName; -import org.spongycastle.x509.*; - -/** - * A simple exmple that generates an attribute certificate. - */ -public class AttrCertExample -{ - static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator(); - static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator(); - - /** - * we generate the CA's certificate - */ - public static X509Certificate createCaCert( - PublicKey pubKey, - PrivateKey privKey) - throws Exception - { - // - // signers name - // - String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // subjects name - the same as we are self signed. - // - String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // create the certificate - version 1 - // - - v1CertGen.setSerialNumber(BigInteger.valueOf(10)); - v1CertGen.setIssuerDN(new X509Principal(issuer)); - v1CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v1CertGen.setSubjectDN(new X509Principal(subject)); - v1CertGen.setPublicKey(pubKey); - v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - X509Certificate cert = v1CertGen.generateX509Certificate(privKey); - - cert.checkValidity(new Date()); - - cert.verify(pubKey); - - return cert; - } - - /** - * we generate a certificate signed by our CA's intermediate certficate - */ - public static X509Certificate createClientCert( - PublicKey pubKey, - PrivateKey caPrivKey, - PublicKey caPubKey) - throws Exception - { - // - // issuer - // - String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate"; - - // - // subjects name table. - // - Hashtable attrs = new Hashtable(); - Vector order = new Vector(); - - attrs.put(X509Principal.C, "AU"); - attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); - attrs.put(X509Principal.L, "Melbourne"); - attrs.put(X509Principal.CN, "Eric H. Echidna"); - attrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); - - order.addElement(X509Principal.C); - order.addElement(X509Principal.O); - order.addElement(X509Principal.L); - order.addElement(X509Principal.CN); - order.addElement(X509Principal.EmailAddress); - - // - // create the certificate - version 3 - // - v3CertGen.reset(); - - v3CertGen.setSerialNumber(BigInteger.valueOf(20)); - v3CertGen.setIssuerDN(new X509Principal(issuer)); - v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); - v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30))); - v3CertGen.setSubjectDN(new X509Principal(order, attrs)); - v3CertGen.setPublicKey(pubKey); - v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // - // add the extensions - // - - v3CertGen.addExtension( - MiscObjectIdentifiers.netscapeCertType, - false, - new NetscapeCertType(NetscapeCertType.objectSigning | NetscapeCertType.smime)); - - X509Certificate cert = v3CertGen.generateX509Certificate(caPrivKey); - - cert.checkValidity(new Date()); - - cert.verify(caPubKey); - - return cert; - } - - public static void main(String args[]) - throws Exception - { - Security.addProvider(new BouncyCastleProvider()); - - // - // personal keys - // - RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16), - new BigInteger("11", 16), - new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16), - new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16), - new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16), - new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16), - new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16), - new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16)); - - // - // ca keys - // - RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16)); - - RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec( - new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16), - new BigInteger("11", 16), - new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16), - new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16), - new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16), - new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16), - new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16), - new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16)); - - // - // set up the keys - // - KeyFactory fact = KeyFactory.getInstance("RSA", "SC"); - PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec); - PublicKey caPubKey = fact.generatePublic(caPubKeySpec); - PrivateKey privKey = fact.generatePrivate(privKeySpec); - PublicKey pubKey = fact.generatePublic(pubKeySpec); - - // - // note in this case we are using the CA certificate for both the client cetificate - // and the attribute certificate. This is to make the vcode simpler to read, in practice - // the CA for the attribute certificate should be different to that of the client certificate - // - X509Certificate caCert = createCaCert(caPubKey, caPrivKey); - X509Certificate clientCert = createClientCert(pubKey, caPrivKey, caPubKey); - - // Einen neuen Attributzertifikatsgenerator instantiieren - X509V2AttributeCertificateGenerator acGen = new X509V2AttributeCertificateGenerator(); - - acGen.reset(); - - /* - * Holder setzen hier als IssuerSerial Issuer und Serial sind ein - * eindeutiger Schl�ssel f�r ein Client Zertifikat! - */ - - acGen.setHolder(new AttributeCertificateHolder(clientCert)); - - // Issuer setzen - - acGen.setIssuer(new AttributeCertificateIssuer(PrincipalUtil.getSubjectX509Principal(caCert))); - - // Serial Number (frei gew�hlt) - acGen.setSerialNumber(new BigInteger("1")); - - // not Before - acGen.setNotBefore(new Date(System.currentTimeMillis() - 50000)); - - // not After - acGen.setNotAfter(new Date(System.currentTimeMillis() + 50000)); - - // signature Algorithmus - acGen.setSignatureAlgorithm("SHA1WithRSAEncryption"); - - // Die eigentlichen Attribute - GeneralName roleName = new GeneralName(GeneralName.rfc822Name, "DAU123456789"); - ASN1EncodableVector roleSyntax = new ASN1EncodableVector(); - roleSyntax.add(roleName); - - // roleSyntax OID: 2.5.24.72 - X509Attribute attributes = new X509Attribute("2.5.24.72", - new DERSequence(roleSyntax)); - - acGen.addAttribute(attributes); - - // Privaten Schluessel der CA lesen - - // Und noch signieren - X509V2AttributeCertificate att = (X509V2AttributeCertificate)acGen - .generateCertificate(caPrivKey, "SC"); - - // Hier ist das Attributzertifikat fertig im Speicher, jetzt testen: - - // Holder - - AttributeCertificateHolder h = att.getHolder(); - if (h.match(clientCert)) - { - System.out.println("Matches original client x509 cert"); - } - - // Issuer - - AttributeCertificateIssuer issuer = att.getIssuer(); - if (issuer.match(caCert)) - { - System.out.println("Matches original ca x509 cert"); - } - - // Dates - System.out.println("valid not before: " + att.getNotBefore()); - System.out.println("valid not before: " + att.getNotAfter()); - - // Dates checken (bc wirft NotValid Exception wenn nicht g�ltig) - - try - { - att.checkValidity(); - att.checkValidity(new Date()); - } - catch (Exception e) - { - System.out.println(e); - } - - // verify - - try - { - att.verify(caPubKey, "SC"); - } - catch (Exception e) - { - System.out.println(e); - } - - // Attribute - X509Attribute[] attribs = att.getAttributes(); - System.out.println("cert has " + attribs.length + " attributes:"); - for (int i = 0; i < attribs.length; i++) - { - X509Attribute a = attribs[i]; - System.out.println("OID: " + a.getOID()); - if (a.getOID().equals("2.5.24.72")) - { - System.out.println("rolesyntax read from cert!"); - } - } - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java index 977725807..5c91202b1 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java @@ -235,26 +235,14 @@ public class BCECPrivateKey } else { - ECParameterSpec p = (ECParameterSpec)ecSpec; - ECCurve curve = p.getG().getCurve(); - ECPoint generator; - - if (curve instanceof ECCurve.Fp) - { - generator = new ECPoint.Fp(curve, p.getG().getX(), p.getG().getY(), withCompression); - } - else if (curve instanceof ECCurve.F2m) - { - generator = new ECPoint.F2m(curve, p.getG().getX(), p.getG().getY(), withCompression); - } - else - { - throw new UnsupportedOperationException("Subclass of ECPoint " + curve.getClass().toString() + "not supported"); - } - + ECParameterSpec p = (ECParameterSpec)ecSpec; + + ECPoint pG = p.getG().normalize(); + ECPoint g = pG.getCurve().createPoint(pG.getAffineXCoord().toBigInteger(), pG.getAffineYCoord().toBigInteger()); + X9ECParameters ecP = new X9ECParameters( p.getCurve(), - generator, + g, p.getN(), p.getH(), p.getSeed()); diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index 9b93da86d..8f704ddc9 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -9,7 +9,7 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; @@ -241,11 +241,11 @@ public class BCECPublicKey X962Parameters params = null; if (ecSpec instanceof ECNamedCurveParameterSpec) { - DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveParameterSpec)ecSpec).getName()); + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveParameterSpec)ecSpec).getName()); if (curveOid == null) { - curveOid = new DERObjectIdentifier(((ECNamedCurveParameterSpec)ecSpec).getName()); + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveParameterSpec)ecSpec).getName()); } params = new X962Parameters(curveOid); } diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index e1cd11b96..27c2eed1d 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -15,7 +15,7 @@ import javax.crypto.SecretKey; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.x9.X9IntegerConverter; @@ -185,7 +185,7 @@ public class KeyAgreementSpi int keySize = ((Integer)algorithms.get(algorithm)).intValue(); - DHKDFParameters params = new DHKDFParameters(new DERObjectIdentifier(algorithm), keySize, secret); + DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret); byte[] keyBytes = new byte[keySize / 8]; kdf.init(params); diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java index 6119af8bf..9d61a76bc 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java @@ -11,7 +11,7 @@ import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Encoding; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.crypto.CipherParameters; @@ -270,8 +270,8 @@ public class SignatureSpi { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERInteger(r)); - v.add(new DERInteger(s)); + v.add(new ASN1Integer(r)); + v.add(new ASN1Integer(s)); return new DERSequence(v).getEncoded(ASN1Encoding.DER); } @@ -283,8 +283,8 @@ public class SignatureSpi ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); BigInteger[] sig = new BigInteger[2]; - sig[0] = ((DERInteger)s.getObjectAt(0)).getValue(); - sig[1] = ((DERInteger)s.getObjectAt(1)).getValue(); + sig[0] = ((ASN1Integer)s.getObjectAt(0)).getValue(); + sig[1] = ((ASN1Integer)s.getObjectAt(1)).getValue(); return sig; } diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java index 43720d247..d322a172e 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java @@ -209,26 +209,14 @@ public class BCECGOST3410PrivateKey } else { - ECParameterSpec p = (ECParameterSpec)ecSpec; - ECCurve curve = p.getG().getCurve(); - ECPoint generator; - - if (curve instanceof ECCurve.Fp) - { - generator = new ECPoint.Fp(curve, p.getG().getX(), p.getG().getY(), withCompression); - } - else if (curve instanceof ECCurve.F2m) - { - generator = new ECPoint.F2m(curve, p.getG().getX(), p.getG().getY(), withCompression); - } - else - { - throw new UnsupportedOperationException("Subclass of ECPoint " + curve.getClass().toString() + "not supported"); - } - + ECParameterSpec p = (ECParameterSpec)ecSpec; + + ECPoint pG = p.getG().normalize(); + ECPoint g = pG.getCurve().createPoint(pG.getAffineXCoord().toBigInteger(), pG.getAffineYCoord().toBigInteger()); + X9ECParameters ecP = new X9ECParameters( p.getCurve(), - generator, + g, p.getN(), p.getH(), p.getSeed()); diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java index 2256bfd18..75e6e1155 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PublicKey.java @@ -12,7 +12,7 @@ import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.DERBitString; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DEROctetString; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.cryptopro.ECGOST3410NamedCurves; @@ -320,11 +320,11 @@ public class BCECGOST3410PublicKey X962Parameters params = null; if (ecSpec instanceof ECNamedCurveParameterSpec) { - DERObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveParameterSpec)ecSpec).getName()); + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveParameterSpec)ecSpec).getName()); if (curveOid == null) { - curveOid = new DERObjectIdentifier(((ECNamedCurveParameterSpec)ecSpec).getName()); + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveParameterSpec)ecSpec).getName()); } params = new X962Parameters(curveOid); } diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index a3909fd99..dbad77728 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -71,6 +71,8 @@ import org.spongycastle.asn1.x509.Extension; import org.spongycastle.asn1.x509.SubjectKeyIdentifier; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; import org.spongycastle.asn1.x509.X509ObjectIdentifiers; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.digests.SHA1Digest; import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.spongycastle.jcajce.provider.util.SecretKeyUtil; import org.spongycastle.jce.interfaces.BCKeyStore; @@ -191,7 +193,7 @@ public class PKCS12KeyStoreSpi SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( (ASN1Sequence)ASN1Primitive.fromByteArray(pubKey.getEncoded())); - return new SubjectKeyIdentifier(info); + return new SubjectKeyIdentifier(getDigest(info)); } catch (Exception e) { @@ -199,6 +201,17 @@ public class PKCS12KeyStoreSpi } } + private static byte[] getDigest(SubjectPublicKeyInfo spki) + { + Digest digest = new SHA1Digest(); + byte[] resBuf = new byte[digest.getDigestSize()]; + + byte[] bytes = spki.getPublicKeyData().getBytes(); + digest.update(bytes, 0, bytes.length); + digest.doFinal(resBuf, 0); + return resBuf; + } + public void setRandom( SecureRandom rand) { diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/CertPathValidatorUtilities.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/CertPathValidatorUtilities.java index 9faa1f7f3..e90b38954 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/CertPathValidatorUtilities.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/CertPathValidatorUtilities.java @@ -44,10 +44,10 @@ import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1OutputStream; import org.spongycastle.asn1.ASN1Primitive; import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.DEREnumerated; -import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.ASN1Enumerated; +import org.spongycastle.asn1.ASN1GeneralizedTime; import org.spongycastle.asn1.DERIA5String; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.DERSequence; import org.spongycastle.asn1.isismtt.ISISMTTObjectIdentifiers; import org.spongycastle.asn1.x509.AlgorithmIdentifier; @@ -456,7 +456,7 @@ public class CertPathValidatorUtilities protected static boolean processCertD1i( int index, List[] policyNodes, - DERObjectIdentifier pOid, + ASN1ObjectIdentifier pOid, Set pq) { List policyNodeVec = policyNodes[index - 1]; @@ -491,7 +491,7 @@ public class CertPathValidatorUtilities protected static void processCertD1ii( int index, List[] policyNodes, - DERObjectIdentifier _poid, + ASN1ObjectIdentifier _poid, Set _pq) { List policyNodeVec = policyNodes[index - 1]; @@ -1030,12 +1030,12 @@ public class CertPathValidatorUtilities } } - DEREnumerated reasonCode = null; + ASN1Enumerated reasonCode = null; if (crl_entry.hasExtensions()) { try { - reasonCode = DEREnumerated + reasonCode = ASN1Enumerated .getInstance(CertPathValidatorUtilities .getExtensionValue(crl_entry, X509Extension.reasonCode.getId())); @@ -1256,13 +1256,13 @@ public class CertPathValidatorUtilities { if (index - 1 == 0) { - DERGeneralizedTime dateOfCertgen = null; + ASN1GeneralizedTime dateOfCertgen = null; try { byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId()); if (extBytes != null) { - dateOfCertgen = DERGeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); + dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes)); } } catch (IOException e) diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java deleted file mode 100644 index 5efc5ea83..000000000 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/JDKPKCS12KeyStore.java +++ /dev/null @@ -1,1565 +0,0 @@ -package org.spongycastle.jce.provider; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.Key; -import java.security.KeyStoreException; -import java.security.KeyStoreSpi; -import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.security.PrivateKey; -import java.security.Provider; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.UnrecoverableKeyException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Date; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; - -import org.spongycastle.asn1.ASN1Encodable; -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1InputStream; -import org.spongycastle.asn1.ASN1Object; -import org.spongycastle.asn1.ASN1ObjectIdentifier; -import org.spongycastle.asn1.ASN1OctetString; -import org.spongycastle.asn1.ASN1Primitive; -import org.spongycastle.asn1.ASN1Sequence; -import org.spongycastle.asn1.ASN1Set; -import org.spongycastle.asn1.BERConstructedOctetString; -import org.spongycastle.asn1.BEROutputStream; -import org.spongycastle.asn1.DERBMPString; -import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DEROctetString; -import org.spongycastle.asn1.DERSequence; -import org.spongycastle.asn1.DERSet; -import org.spongycastle.asn1.pkcs.AuthenticatedSafe; -import org.spongycastle.asn1.pkcs.CertBag; -import org.spongycastle.asn1.pkcs.ContentInfo; -import org.spongycastle.asn1.pkcs.EncryptedData; -import org.spongycastle.asn1.pkcs.MacData; -import org.spongycastle.asn1.pkcs.PKCS12PBEParams; -import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.spongycastle.asn1.pkcs.Pfx; -import org.spongycastle.asn1.pkcs.SafeBag; -import org.spongycastle.asn1.util.ASN1Dump; -import org.spongycastle.asn1.x509.AlgorithmIdentifier; -import org.spongycastle.asn1.x509.AuthorityKeyIdentifier; -import org.spongycastle.asn1.x509.DigestInfo; -import org.spongycastle.asn1.x509.SubjectKeyIdentifier; -import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.asn1.x509.X509Extensions; -import org.spongycastle.asn1.x509.X509ObjectIdentifiers; -import org.spongycastle.jcajce.provider.symmetric.util.BCPBEKey; -import org.spongycastle.jce.interfaces.BCKeyStore; -import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; -import org.spongycastle.util.Arrays; -import org.spongycastle.util.Strings; -import org.spongycastle.util.encoders.Hex; - -public class JDKPKCS12KeyStore - extends KeyStoreSpi - implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore -{ - private static final int SALT_SIZE = 20; - private static final int MIN_ITERATIONS = 1024; - - private static final Provider bcProvider = new BouncyCastleProvider(); - - private IgnoresCaseHashtable keys = new IgnoresCaseHashtable(); - private Hashtable localIds = new Hashtable(); - private IgnoresCaseHashtable certs = new IgnoresCaseHashtable(); - private Hashtable chainCerts = new Hashtable(); - private Hashtable keyCerts = new Hashtable(); - - // - // generic object types - // - static final int NULL = 0; - static final int CERTIFICATE = 1; - static final int KEY = 2; - static final int SECRET = 3; - static final int SEALED = 4; - - // - // key types - // - static final int KEY_PRIVATE = 0; - static final int KEY_PUBLIC = 1; - static final int KEY_SECRET = 2; - - protected SecureRandom random = new SecureRandom(); - - // use of final causes problems with JDK 1.2 compiler - private CertificateFactory certFact; - private ASN1ObjectIdentifier keyAlgorithm; - private ASN1ObjectIdentifier certAlgorithm; - - private class CertId - { - byte[] id; - - CertId( - PublicKey key) - { - this.id = createSubjectKeyId(key).getKeyIdentifier(); - } - - CertId( - byte[] id) - { - this.id = id; - } - - public int hashCode() - { - return Arrays.hashCode(id); - } - - public boolean equals( - Object o) - { - if (o == this) - { - return true; - } - - if (!(o instanceof CertId)) - { - return false; - } - - CertId cId = (CertId)o; - - return Arrays.areEqual(id, cId.id); - } - } - - public JDKPKCS12KeyStore( - Provider provider, - ASN1ObjectIdentifier keyAlgorithm, - ASN1ObjectIdentifier certAlgorithm) - { - this.keyAlgorithm = keyAlgorithm; - this.certAlgorithm = certAlgorithm; - - try - { - if (provider != null) - { - certFact = CertificateFactory.getInstance("X.509", provider); - } - else - { - certFact = CertificateFactory.getInstance("X.509"); - } - } - catch (Exception e) - { - throw new IllegalArgumentException("can't create cert factory - " + e.toString()); - } - } - - private SubjectKeyIdentifier createSubjectKeyId( - PublicKey pubKey) - { - try - { - SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance( - (ASN1Sequence) ASN1Primitive.fromByteArray(pubKey.getEncoded())); - - return new SubjectKeyIdentifier(info); - } - catch (Exception e) - { - throw new RuntimeException("error creating key"); - } - } - - public void setRandom( - SecureRandom rand) - { - this.random = rand; - } - - public Enumeration engineAliases() - { - Hashtable tab = new Hashtable(); - - Enumeration e = certs.keys(); - while (e.hasMoreElements()) - { - tab.put(e.nextElement(), "cert"); - } - - e = keys.keys(); - while (e.hasMoreElements()) - { - String a = (String)e.nextElement(); - if (tab.get(a) == null) - { - tab.put(a, "key"); - } - } - - return tab.keys(); - } - - public boolean engineContainsAlias( - String alias) - { - return (certs.get(alias) != null || keys.get(alias) != null); - } - - /** - * this is not quite complete - we should follow up on the chain, a bit - * tricky if a certificate appears in more than one chain... - */ - public void engineDeleteEntry( - String alias) - throws KeyStoreException - { - Key k = (Key)keys.remove(alias); - - Certificate c = (Certificate)certs.remove(alias); - - if (c != null) - { - chainCerts.remove(new CertId(c.getPublicKey())); - } - - if (k != null) - { - String id = (String)localIds.remove(alias); - if (id != null) - { - c = (Certificate)keyCerts.remove(id); - } - if (c != null) - { - chainCerts.remove(new CertId(c.getPublicKey())); - } - } - - if (c == null && k == null) - { - throw new KeyStoreException("no such entry as " + alias); - } - } - - /** - * simply return the cert for the private key - */ - public Certificate engineGetCertificate( - String alias) - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getCertificate."); - } - - Certificate c = (Certificate)certs.get(alias); - - // - // look up the key table - and try the local key id - // - if (c == null) - { - String id = (String)localIds.get(alias); - if (id != null) - { - c = (Certificate)keyCerts.get(id); - } - else - { - c = (Certificate)keyCerts.get(alias); - } - } - - return c; - } - - public String engineGetCertificateAlias( - Certificate cert) - { - Enumeration c = certs.elements(); - Enumeration k = certs.keys(); - - while (c.hasMoreElements()) - { - Certificate tc = (Certificate)c.nextElement(); - String ta = (String)k.nextElement(); - - if (tc.equals(cert)) - { - return ta; - } - } - - c = keyCerts.elements(); - k = keyCerts.keys(); - - while (c.hasMoreElements()) - { - Certificate tc = (Certificate)c.nextElement(); - String ta = (String)k.nextElement(); - - if (tc.equals(cert)) - { - return ta; - } - } - - return null; - } - - public Certificate[] engineGetCertificateChain( - String alias) - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getCertificateChain."); - } - - if (!engineIsKeyEntry(alias)) - { - return null; - } - - Certificate c = engineGetCertificate(alias); - - if (c != null) - { - Vector cs = new Vector(); - - while (c != null) - { - X509Certificate x509c = (X509Certificate)c; - Certificate nextC = null; - - byte[] bytes = x509c.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId()); - if (bytes != null) - { - try - { - ASN1InputStream aIn = new ASN1InputStream(bytes); - - byte[] authBytes = ((ASN1OctetString)aIn.readObject()).getOctets(); - aIn = new ASN1InputStream(authBytes); - - AuthorityKeyIdentifier id = AuthorityKeyIdentifier.getInstance(aIn.readObject()); - if (id.getKeyIdentifier() != null) - { - nextC = (Certificate)chainCerts.get(new CertId(id.getKeyIdentifier())); - } - - } - catch (IOException e) - { - throw new RuntimeException(e.toString()); - } - } - - if (nextC == null) - { - // - // no authority key id, try the Issuer DN - // - Principal i = x509c.getIssuerDN(); - Principal s = x509c.getSubjectDN(); - - if (!i.equals(s)) - { - Enumeration e = chainCerts.keys(); - - while (e.hasMoreElements()) - { - X509Certificate crt = (X509Certificate)chainCerts.get(e.nextElement()); - Principal sub = crt.getSubjectDN(); - if (sub.equals(i)) - { - try - { - x509c.verify(crt.getPublicKey()); - nextC = crt; - break; - } - catch (Exception ex) - { - // continue - } - } - } - } - } - - cs.addElement(c); - if (nextC != c) // self signed - end of the chain - { - c = nextC; - } - else - { - c = null; - } - } - - Certificate[] certChain = new Certificate[cs.size()]; - - for (int i = 0; i != certChain.length; i++) - { - certChain[i] = (Certificate)cs.elementAt(i); - } - - return certChain; - } - - return null; - } - - public Date engineGetCreationDate(String alias) - { - return new Date(); - } - - public Key engineGetKey( - String alias, - char[] password) - throws NoSuchAlgorithmException, UnrecoverableKeyException - { - if (alias == null) - { - throw new IllegalArgumentException("null alias passed to getKey."); - } - - return (Key)keys.get(alias); - } - - public boolean engineIsCertificateEntry( - String alias) - { - return (certs.get(alias) != null && keys.get(alias) == null); - } - - public boolean engineIsKeyEntry( - String alias) - { - return (keys.get(alias) != null); - } - - public void engineSetCertificateEntry( - String alias, - Certificate cert) - throws KeyStoreException - { - if (keys.get(alias) != null) - { - throw new KeyStoreException("There is a key entry with the name " + alias + "."); - } - - certs.put(alias, cert); - chainCerts.put(new CertId(cert.getPublicKey()), cert); - } - - public void engineSetKeyEntry( - String alias, - byte[] key, - Certificate[] chain) - throws KeyStoreException - { - throw new RuntimeException("operation not supported"); - } - - public void engineSetKeyEntry( - String alias, - Key key, - char[] password, - Certificate[] chain) - throws KeyStoreException - { - if ((key instanceof PrivateKey) && (chain == null)) - { - throw new KeyStoreException("no certificate chain for private key"); - } - - if (keys.get(alias) != null) - { - engineDeleteEntry(alias); - } - - keys.put(alias, key); - certs.put(alias, chain[0]); - - for (int i = 0; i != chain.length; i++) - { - chainCerts.put(new CertId(chain[i].getPublicKey()), chain[i]); - } - } - - public int engineSize() - { - Hashtable tab = new Hashtable(); - - Enumeration e = certs.keys(); - while (e.hasMoreElements()) - { - tab.put(e.nextElement(), "cert"); - } - - e = keys.keys(); - while (e.hasMoreElements()) - { - String a = (String)e.nextElement(); - if (tab.get(a) == null) - { - tab.put(a, "key"); - } - } - - return tab.size(); - } - - protected PrivateKey unwrapKey( - AlgorithmIdentifier algId, - byte[] data, - char[] password, - boolean wrongPKCS12Zero) - throws IOException - { - String algorithm = algId.getObjectId().getId(); - PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); - - PBEKeySpec pbeSpec = new PBEKeySpec(password); - PrivateKey out; - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance( - algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - - SecretKey k = keyFact.generateSecret(pbeSpec); - - ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - - cipher.init(Cipher.UNWRAP_MODE, k, defParams); - - // we pass "" as the key algorithm type as it is unknown at this point - out = (PrivateKey)cipher.unwrap(data, "", Cipher.PRIVATE_KEY); - } - catch (Exception e) - { - throw new IOException("exception unwrapping private key - " + e.toString()); - } - - return out; - } - - protected byte[] wrapKey( - String algorithm, - Key key, - PKCS12PBEParams pbeParams, - char[] password) - throws IOException - { - PBEKeySpec pbeSpec = new PBEKeySpec(password); - byte[] out; - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance( - algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - - cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams); - - out = cipher.wrap(key); - } - catch (Exception e) - { - throw new IOException("exception encrypting data - " + e.toString()); - } - - return out; - } - - protected byte[] cryptData( - boolean forEncryption, - AlgorithmIdentifier algId, - char[] password, - boolean wrongPKCS12Zero, - byte[] data) - throws IOException - { - String algorithm = algId.getObjectId().getId(); - PKCS12PBEParams pbeParams = PKCS12PBEParams.getInstance(algId.getParameters()); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - - try - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec( - pbeParams.getIV(), - pbeParams.getIterations().intValue()); - BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec); - - key.setTryWrongPKCS12Zero(wrongPKCS12Zero); - - Cipher cipher = Cipher.getInstance(algorithm, bcProvider); - int mode = forEncryption ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE; - cipher.init(mode, key, defParams); - return cipher.doFinal(data); - } - catch (Exception e) - { - throw new IOException("exception decrypting data - " + e.toString()); - } - } - - public void engineLoad( - InputStream stream, - char[] password) - throws IOException - { - if (stream == null) // just initialising - { - return; - } - - if (password == null) - { - throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); - } - - BufferedInputStream bufIn = new BufferedInputStream(stream); - - bufIn.mark(10); - - int head = bufIn.read(); - - if (head != 0x30) - { - throw new IOException("stream does not represent a PKCS12 key store"); - } - - bufIn.reset(); - - ASN1InputStream bIn = new ASN1InputStream(bufIn); - ASN1Sequence obj = (ASN1Sequence)bIn.readObject(); - Pfx bag = Pfx.getInstance(obj); - ContentInfo info = bag.getAuthSafe(); - Vector chain = new Vector(); - boolean unmarkedKey = false; - boolean wrongPKCS12Zero = false; - - if (bag.getMacData() != null) // check the mac code - { - MacData mData = bag.getMacData(); - DigestInfo dInfo = mData.getMac(); - AlgorithmIdentifier algId = dInfo.getAlgorithmId(); - byte[] salt = mData.getSalt(); - int itCount = mData.getIterationCount().intValue(); - - byte[] data = ((ASN1OctetString)info.getContent()).getOctets(); - - try - { - byte[] res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, false, data); - byte[] dig = dInfo.getDigest(); - - if (!Arrays.constantTimeAreEqual(res, dig)) - { - if (password.length > 0) - { - throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); - } - - // Try with incorrect zero length password - res = calculatePbeMac(algId.getObjectId(), salt, itCount, password, true, data); - - if (!Arrays.constantTimeAreEqual(res, dig)) - { - throw new IOException("PKCS12 key store mac invalid - wrong password or corrupted file."); - } - - wrongPKCS12Zero = true; - } - } - catch (IOException e) - { - throw e; - } - catch (Exception e) - { - throw new IOException("error constructing MAC: " + e.toString()); - } - } - - keys = new IgnoresCaseHashtable(); - localIds = new Hashtable(); - - if (info.getContentType().equals(data)) - { - bIn = new ASN1InputStream(((ASN1OctetString)info.getContent()).getOctets()); - - AuthenticatedSafe authSafe = AuthenticatedSafe.getInstance(bIn.readObject()); - ContentInfo[] c = authSafe.getContentInfo(); - - for (int i = 0; i != c.length; i++) - { - if (c[i].getContentType().equals(data)) - { - ASN1InputStream dIn = new ASN1InputStream(((ASN1OctetString)c[i].getContent()).getOctets()); - ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); - - for (int j = 0; j != seq.size(); j++) - { - SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); - if (b.getBagId().equals(pkcs8ShroudedKeyBag)) - { - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); - PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - if (b.getBagAttributes() != null) - { - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); - ASN1Object attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Object)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - } - - if (localId != null) - { - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else - { - unmarkedKey = true; - keys.put("unmarked", privKey); - } - } - else if (b.getBagId().equals(certBag)) - { - chain.addElement(b); - } - else - { - System.out.println("extra in data " + b.getBagId()); - System.out.println(ASN1Dump.dumpAsString(b)); - } - } - } - else if (c[i].getContentType().equals(encryptedData)) - { - EncryptedData d = EncryptedData.getInstance(c[i].getContent()); - byte[] octets = cryptData(false, d.getEncryptionAlgorithm(), - password, wrongPKCS12Zero, d.getContent().getOctets()); - ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(octets); - - for (int j = 0; j != seq.size(); j++) - { - SafeBag b = SafeBag.getInstance(seq.getObjectAt(j)); - - if (b.getBagId().equals(certBag)) - { - chain.addElement(b); - } - else if (b.getBagId().equals(pkcs8ShroudedKeyBag)) - { - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance(b.getBagValue()); - PrivateKey privKey = unwrapKey(eIn.getEncryptionAlgorithm(), eIn.getEncryptedData(), password, wrongPKCS12Zero); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet= (ASN1Set)sq.getObjectAt(1); - ASN1Object attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Object)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else if (b.getBagId().equals(keyBag)) - { - org.spongycastle.asn1.pkcs.PrivateKeyInfo kInfo = new org.spongycastle.asn1.pkcs.PrivateKeyInfo((ASN1Sequence)b.getBagValue()); - PrivateKey privKey = BouncyCastleProvider.getPrivateKey(kInfo); - - // - // set the attributes on the key - // - PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)privKey; - String alias = null; - ASN1OctetString localId = null; - - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier aOid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Set attrSet = (ASN1Set)sq.getObjectAt(1); - ASN1Object attr = null; - - if (attrSet.size() > 0) - { - attr = (ASN1Object)attrSet.getObjectAt(0); - - ASN1Encodable existing = bagAttr.getBagAttribute(aOid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(aOid, attr); - } - } - - if (aOid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - keys.put(alias, privKey); - } - else if (aOid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - - String name = new String(Hex.encode(localId.getOctets())); - - if (alias == null) - { - keys.put(name, privKey); - } - else - { - localIds.put(alias, name); - } - } - else - { - System.out.println("extra in encryptedData " + b.getBagId()); - System.out.println(ASN1Dump.dumpAsString(b)); - } - } - } - else - { - System.out.println("extra " + c[i].getContentType().getId()); - System.out.println("extra " + ASN1Dump.dumpAsString(c[i].getContent())); - } - } - } - - certs = new IgnoresCaseHashtable(); - chainCerts = new Hashtable(); - keyCerts = new Hashtable(); - - for (int i = 0; i != chain.size(); i++) - { - SafeBag b = (SafeBag)chain.elementAt(i); - CertBag cb = CertBag.getInstance(b.getBagValue()); - - if (!cb.getCertId().equals(x509Certificate)) - { - throw new RuntimeException("Unsupported certificate type: " + cb.getCertId()); - } - - Certificate cert; - - try - { - ByteArrayInputStream cIn = new ByteArrayInputStream( - ((ASN1OctetString)cb.getCertValue()).getOctets()); - cert = certFact.generateCertificate(cIn); - } - catch (Exception e) - { - throw new RuntimeException(e.toString()); - } - - // - // set the attributes - // - ASN1OctetString localId = null; - String alias = null; - - if (b.getBagAttributes() != null) - { - Enumeration e = b.getBagAttributes().getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence sq = (ASN1Sequence)e.nextElement(); - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)sq.getObjectAt(0); - ASN1Object attr = (ASN1Object)((ASN1Set)sq.getObjectAt(1)).getObjectAt(0); - PKCS12BagAttributeCarrier bagAttr = null; - - if (cert instanceof PKCS12BagAttributeCarrier) - { - bagAttr = (PKCS12BagAttributeCarrier)cert; - - ASN1Encodable existing = bagAttr.getBagAttribute(oid); - if (existing != null) - { - // OK, but the value has to be the same - if (!existing.toASN1Primitive().equals(attr)) - { - throw new IOException( - "attempt to add existing attribute with different value"); - } - } - else - { - bagAttr.setBagAttribute(oid, attr); - } - } - - if (oid.equals(pkcs_9_at_friendlyName)) - { - alias = ((DERBMPString)attr).getString(); - } - else if (oid.equals(pkcs_9_at_localKeyId)) - { - localId = (ASN1OctetString)attr; - } - } - } - - chainCerts.put(new CertId(cert.getPublicKey()), cert); - - if (unmarkedKey) - { - if (keyCerts.isEmpty()) - { - String name = new String(Hex.encode(createSubjectKeyId(cert.getPublicKey()).getKeyIdentifier())); - - keyCerts.put(name, cert); - keys.put(name, keys.remove("unmarked")); - } - } - else - { - // - // the local key id needs to override the friendly name - // - if (localId != null) - { - String name = new String(Hex.encode(localId.getOctets())); - - keyCerts.put(name, cert); - } - if (alias != null) - { - certs.put(alias, cert); - } - } - } - } - - public void engineStore(OutputStream stream, char[] password) - throws IOException - { - if (password == null) - { - throw new NullPointerException("No password supplied for PKCS#12 KeyStore."); - } - - // - // handle the key - // - ASN1EncodableVector keyS = new ASN1EncodableVector(); - - - Enumeration ks = keys.keys(); - - while (ks.hasMoreElements()) - { - byte[] kSalt = new byte[SALT_SIZE]; - - random.nextBytes(kSalt); - - String name = (String)ks.nextElement(); - PrivateKey privKey = (PrivateKey)keys.get(name); - PKCS12PBEParams kParams = new PKCS12PBEParams(kSalt, MIN_ITERATIONS); - byte[] kBytes = wrapKey(keyAlgorithm.getId(), privKey, kParams, password); - AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(keyAlgorithm, kParams.toASN1Object()); - org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo kInfo = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, kBytes); - boolean attrSet = false; - ASN1EncodableVector kName = new ASN1EncodableVector(); - - if (privKey instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)privKey; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(name)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); - } - - // - // make sure we have a local key-id - // - if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) - { - Certificate ct = engineGetCertificate(name); - - bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(ct.getPublicKey())); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - ASN1EncodableVector kSeq = new ASN1EncodableVector(); - - kSeq.add(oid); - kSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - - attrSet = true; - - kName.add(new DERSequence(kSeq)); - } - } - - if (!attrSet) - { - // - // set a default friendly name (from the key id) and local id - // - ASN1EncodableVector kSeq = new ASN1EncodableVector(); - Certificate ct = engineGetCertificate(name); - - kSeq.add(pkcs_9_at_localKeyId); - kSeq.add(new DERSet(createSubjectKeyId(ct.getPublicKey()))); - - kName.add(new DERSequence(kSeq)); - - kSeq = new ASN1EncodableVector(); - - kSeq.add(pkcs_9_at_friendlyName); - kSeq.add(new DERSet(new DERBMPString(name))); - - kName.add(new DERSequence(kSeq)); - } - - SafeBag kBag = new SafeBag(pkcs8ShroudedKeyBag, kInfo.toASN1Object(), new DERSet(kName)); - keyS.add(kBag); - } - - byte[] keySEncoded = new DERSequence(keyS).getEncoded(); - BERConstructedOctetString keyString = new BERConstructedOctetString(keySEncoded); - - // - // certificate processing - // - byte[] cSalt = new byte[SALT_SIZE]; - - random.nextBytes(cSalt); - - ASN1EncodableVector certSeq = new ASN1EncodableVector(); - PKCS12PBEParams cParams = new PKCS12PBEParams(cSalt, MIN_ITERATIONS); - AlgorithmIdentifier cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.toASN1Object()); - Hashtable doneCerts = new Hashtable(); - - Enumeration cs = keys.keys(); - while (cs.hasMoreElements()) - { - try - { - String name = (String)cs.nextElement(); - Certificate cert = engineGetCertificate(name); - boolean cAttrSet = false; - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(name)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(name)); - } - - // - // make sure we have a local key-id - // - if (bagAttrs.getBagAttribute(pkcs_9_at_localKeyId) == null) - { - bagAttrs.setBagAttribute(pkcs_9_at_localKeyId, createSubjectKeyId(cert.getPublicKey())); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - - cAttrSet = true; - } - } - - if (!cAttrSet) - { - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_localKeyId); - fSeq.add(new DERSet(createSubjectKeyId(cert.getPublicKey()))); - fName.add(new DERSequence(fSeq)); - - fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_friendlyName); - fSeq.add(new DERSet(new DERBMPString(name))); - - fName.add(new DERSequence(fSeq)); - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Object(), new DERSet(fName)); - - certSeq.add(sBag); - - doneCerts.put(cert, cert); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - cs = certs.keys(); - while (cs.hasMoreElements()) - { - try - { - String certId = (String)cs.nextElement(); - Certificate cert = (Certificate)certs.get(certId); - boolean cAttrSet = false; - - if (keys.get(certId) != null) - { - continue; - } - - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - // - // make sure we are using the local alias on store - // - DERBMPString nm = (DERBMPString)bagAttrs.getBagAttribute(pkcs_9_at_friendlyName); - if (nm == null || !nm.getString().equals(certId)) - { - bagAttrs.setBagAttribute(pkcs_9_at_friendlyName, new DERBMPString(certId)); - } - - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - - // a certificate not immediately linked to a key doesn't require - // a localKeyID and will confuse some PKCS12 implementations. - // - // If we find one, we'll prune it out. - if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) - { - continue; - } - - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - - cAttrSet = true; - } - } - - if (!cAttrSet) - { - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(pkcs_9_at_friendlyName); - fSeq.add(new DERSet(new DERBMPString(certId))); - - fName.add(new DERSequence(fSeq)); - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Object(), new DERSet(fName)); - - certSeq.add(sBag); - - doneCerts.put(cert, cert); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - cs = chainCerts.keys(); - while (cs.hasMoreElements()) - { - try - { - CertId certId = (CertId)cs.nextElement(); - Certificate cert = (Certificate)chainCerts.get(certId); - - if (doneCerts.get(cert) != null) - { - continue; - } - - CertBag cBag = new CertBag( - x509Certificate, - new DEROctetString(cert.getEncoded())); - ASN1EncodableVector fName = new ASN1EncodableVector(); - - if (cert instanceof PKCS12BagAttributeCarrier) - { - PKCS12BagAttributeCarrier bagAttrs = (PKCS12BagAttributeCarrier)cert; - Enumeration e = bagAttrs.getBagAttributeKeys(); - - while (e.hasMoreElements()) - { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); - - // a certificate not immediately linked to a key doesn't require - // a localKeyID and will confuse some PKCS12 implementations. - // - // If we find one, we'll prune it out. - if (oid.equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId)) - { - continue; - } - - ASN1EncodableVector fSeq = new ASN1EncodableVector(); - - fSeq.add(oid); - fSeq.add(new DERSet(bagAttrs.getBagAttribute(oid))); - fName.add(new DERSequence(fSeq)); - } - } - - SafeBag sBag = new SafeBag(certBag, cBag.toASN1Object(), new DERSet(fName)); - - certSeq.add(sBag); - } - catch (CertificateEncodingException e) - { - throw new IOException("Error encoding certificate: " + e.toString()); - } - } - - byte[] certSeqEncoded = new DERSequence(certSeq).getEncoded(); - byte[] certBytes = cryptData(true, cAlgId, password, false, certSeqEncoded); - EncryptedData cInfo = new EncryptedData(data, cAlgId, new BERConstructedOctetString(certBytes)); - - ContentInfo[] info = new ContentInfo[] - { - new ContentInfo(data, keyString), - new ContentInfo(encryptedData, cInfo.toASN1Object()) - }; - - AuthenticatedSafe auth = new AuthenticatedSafe(info); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - BEROutputStream berOut = new BEROutputStream(bOut); - - berOut.writeObject(auth); - - byte[] pkg = bOut.toByteArray(); - - ContentInfo mainInfo = new ContentInfo(data, new BERConstructedOctetString(pkg)); - - // - // create the mac - // - byte[] mSalt = new byte[20]; - int itCount = MIN_ITERATIONS; - - random.nextBytes(mSalt); - - byte[] data = ((ASN1OctetString)mainInfo.getContent()).getOctets(); - - MacData mData; - - try - { - byte[] res = calculatePbeMac(id_SHA1, mSalt, itCount, password, false, data); - - AlgorithmIdentifier algId = new AlgorithmIdentifier(id_SHA1, new DERNull()); - DigestInfo dInfo = new DigestInfo(algId, res); - - mData = new MacData(dInfo, mSalt, itCount); - } - catch (Exception e) - { - throw new IOException("error constructing MAC: " + e.toString()); - } - - // - // output the Pfx - // - Pfx pfx = new Pfx(mainInfo, mData); - - berOut = new BEROutputStream(stream); - - berOut.writeObject(pfx); - } - - private static byte[] calculatePbeMac( - ASN1ObjectIdentifier oid, - byte[] salt, - int itCount, - char[] password, - boolean wrongPkcs12Zero, - byte[] data) - throws Exception - { - SecretKeyFactory keyFact = SecretKeyFactory.getInstance(oid.getId(), bcProvider); - PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount); - PBEKeySpec pbeSpec = new PBEKeySpec(password); - BCPBEKey key = (BCPBEKey) keyFact.generateSecret(pbeSpec); - key.setTryWrongPKCS12Zero(wrongPkcs12Zero); - - Mac mac = Mac.getInstance(oid.getId(), bcProvider); - mac.init(key, defParams); - mac.update(data); - return mac.doFinal(); - } - - public static class BCPKCS12KeyStore - extends JDKPKCS12KeyStore - { - public BCPKCS12KeyStore() - { - super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); - } - } - - public static class BCPKCS12KeyStore3DES - extends JDKPKCS12KeyStore - { - public BCPKCS12KeyStore3DES() - { - super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); - } - } - - public static class DefPKCS12KeyStore - extends JDKPKCS12KeyStore - { - public DefPKCS12KeyStore() - { - super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC); - } - } - - public static class DefPKCS12KeyStore3DES - extends JDKPKCS12KeyStore - { - public DefPKCS12KeyStore3DES() - { - super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC); - } - } - - private static class IgnoresCaseHashtable - { - private Hashtable orig = new Hashtable(); - private Hashtable keys = new Hashtable(); - - public void put(String key, Object value) - { - String lower = Strings.toLowerCase(key); - String k = (String)keys.get(lower); - if (k != null) - { - orig.remove(k); - } - - keys.put(lower, key); - orig.put(key, value); - } - - public Enumeration keys() - { - return orig.keys(); - } - - public Object remove(String alias) - { - String k = (String)keys.remove(Strings.toLowerCase(alias)); - if (k == null) - { - return null; - } - - return orig.remove(k); - } - - public Object get(String alias) - { - String k = (String)keys.get(Strings.toLowerCase(alias)); - if (k == null) - { - return null; - } - - return orig.get(k); - } - - public Enumeration elements() - { - return orig.elements(); - } - } -} diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/X509SignatureUtil.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/X509SignatureUtil.java index 48d24344d..93cce7a49 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/X509SignatureUtil.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/jce/provider/X509SignatureUtil.java @@ -8,7 +8,7 @@ import java.security.SignatureException; import org.spongycastle.asn1.ASN1Encodable; import org.spongycastle.asn1.ASN1Null; import org.spongycastle.asn1.DERNull; -import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.spongycastle.asn1.nist.NISTObjectIdentifiers; import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; @@ -75,7 +75,7 @@ class X509SignatureUtil * representations rather the the algorithm identifier (if possible). */ private static String getDigestAlgName( - DERObjectIdentifier digestAlgOID) + ASN1ObjectIdentifier digestAlgOID) { if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) { diff --git a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java index c4172969f..4748bfc51 100644 --- a/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java +++ b/extern/spongycastle/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java @@ -1,6 +1,6 @@ package org.spongycastle.x509; -import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.x509.X509Extensions; import org.spongycastle.util.Arrays; import org.spongycastle.util.Selector; @@ -96,14 +96,14 @@ public class X509CRLStoreSelector return false; } X509CRL crl = (X509CRL)obj; - DERInteger dci = null; + ASN1Integer dci = null; try { byte[] bytes = crl .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); if (bytes != null) { - dci = DERInteger.getInstance(X509ExtensionUtil + dci = ASN1Integer.getInstance(X509ExtensionUtil .fromExtensionValue(bytes)); } } diff --git a/extern/spongycastle/settings.gradle b/extern/spongycastle/settings.gradle index f2a0485a2..7849b2062 100644 --- a/extern/spongycastle/settings.gradle +++ b/extern/spongycastle/settings.gradle @@ -1,4 +1,3 @@ include "core" -include "pg" include "pkix" include "prov"