summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbouncy <bouncy>2012-03-22 04:12:38 +0000
committerbouncy <bouncy>2012-03-22 04:12:38 +0000
commit627fd07aea6b3c9c5001e3c6f7ca44fbfdd86ec6 (patch)
treed755a1f94c566d52dc0509954a1b43f3165825f7
parent50304828965098734520b1cc56374ed1623eca06 (diff)
downloadandroid_external_spongycastle-627fd07aea6b3c9c5001e3c6f7ca44fbfdd86ec6.tar.gz
android_external_spongycastle-627fd07aea6b3c9c5001e3c6f7ca44fbfdd86ec6.tar.bz2
android_external_spongycastle-627fd07aea6b3c9c5001e3c6f7ca44fbfdd86ec6.zip
core API updates.
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java10
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/ASN1UTCTime.java5
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java57
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/DERUTCTime.java50
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/DateFormatter.java272
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/StreamUtil.java1
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/cms/Time.java65
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/eac/PackedDate.java70
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java189
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/test/RegressionTest.java59
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java98
-rw-r--r--crypto/j2me/org/bouncycastle/asn1/x509/Time.java65
-rw-r--r--crypto/j2me/org/bouncycastle/crypto/test/RSATest.java303
-rw-r--r--crypto/j2me/org/bouncycastle/crypto/test/RegressionTest.java14
-rw-r--r--crypto/j2me/org/bouncycastle/util/Selector.java8
15 files changed, 1167 insertions, 99 deletions
diff --git a/crypto/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/crypto/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java
index 5a01826db..ea2cb3f27 100644
--- a/crypto/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ b/crypto/j2me/org/bouncycastle/asn1/ASN1GeneralizedTime.java
@@ -10,6 +10,16 @@ public class ASN1GeneralizedTime
super(bytes);
}
+ public ASN1GeneralizedTime(Date date)
+ {
+ super(date);
+ }
+
+ public ASN1GeneralizedTime(Date date, boolean includeMillis)
+ {
+ super(date, includeMillis);
+ }
+
public ASN1GeneralizedTime(String time)
{
super(time);
diff --git a/crypto/j2me/org/bouncycastle/asn1/ASN1UTCTime.java b/crypto/j2me/org/bouncycastle/asn1/ASN1UTCTime.java
index e74c5569b..aac76e101 100644
--- a/crypto/j2me/org/bouncycastle/asn1/ASN1UTCTime.java
+++ b/crypto/j2me/org/bouncycastle/asn1/ASN1UTCTime.java
@@ -10,6 +10,11 @@ public class ASN1UTCTime
super(bytes);
}
+ public ASN1UTCTime(Date date)
+ {
+ super(date);
+ }
+
public ASN1UTCTime(String time)
{
super(time);
diff --git a/crypto/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java b/crypto/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java
index 18863e0ae..2cb95b60c 100644
--- a/crypto/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ b/crypto/j2me/org/bouncycastle/asn1/DERGeneralizedTime.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1;
import java.io.IOException;
+import java.util.Date;
import java.util.TimeZone;
import org.bouncycastle.util.Arrays;
@@ -62,7 +63,7 @@ public class DERGeneralizedTime
/**
* 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
+ * 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.
*
@@ -72,9 +73,32 @@ public class DERGeneralizedTime
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);
}
+ /**
+ * base constructer from a java.util.date object
+ */
+ public DERGeneralizedTime(
+ Date time)
+ {
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
+ }
+
+ protected DERGeneralizedTime(Date date, boolean includeMillis)
+ {
+ this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
+ }
+
DERGeneralizedTime(
byte[] bytes)
{
@@ -153,19 +177,19 @@ public class DERGeneralizedTime
}
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
- }
-*/
+
+// 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);
}
@@ -179,6 +203,11 @@ public class DERGeneralizedTime
return Integer.toString(time);
}
+ public Date getDate()
+ {
+ return DateFormatter.fromGeneralizedTimeString(time);
+ }
+
private boolean hasFractionalSeconds()
{
for (int i = 0; i != time.length; i++)
diff --git a/crypto/j2me/org/bouncycastle/asn1/DERUTCTime.java b/crypto/j2me/org/bouncycastle/asn1/DERUTCTime.java
index 26716fde9..3e8010b4b 100644
--- a/crypto/j2me/org/bouncycastle/asn1/DERUTCTime.java
+++ b/crypto/j2me/org/bouncycastle/asn1/DERUTCTime.java
@@ -1,6 +1,7 @@
package org.bouncycastle.asn1;
import java.io.IOException;
+import java.util.Date;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Strings;
@@ -72,9 +73,27 @@ public class DERUTCTime
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);
}
+ /**
+ * base constructor from a java.util.date object
+ */
+ public DERUTCTime(
+ Date time)
+ {
+ this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
+ }
+
DERUTCTime(
byte[] time)
{
@@ -82,6 +101,28 @@ public class DERUTCTime
}
/**
+ * 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).
* <p>
@@ -158,6 +199,15 @@ public class DERUTCTime
}
}
+ /**
+ * 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;
diff --git a/crypto/j2me/org/bouncycastle/asn1/DateFormatter.java b/crypto/j2me/org/bouncycastle/asn1/DateFormatter.java
new file mode 100644
index 000000000..cd7077403
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/asn1/DateFormatter.java
@@ -0,0 +1,272 @@
+package org.bouncycastle.asn1;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+class DateFormatter
+{
+ // YYMMDDHHMMSSZ
+ static String toUTCDateString(Date date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ calendar.setTime(date);
+
+ return format2Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND)) + "Z";
+ }
+
+ static Date adjustedFromUTCDateString(byte[] date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ int year = toInt2(date, 0);
+
+ if (year < 50)
+ {
+ year += 2000;
+ }
+ else
+ {
+ year += 1900;
+ }
+
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, toInt2(date, 2) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 4));
+ calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 6));
+ calendar.set(Calendar.MINUTE, toInt2(date, 8));
+
+ int tzChar = 10;
+
+ if (isNumber(date, tzChar))
+ {
+ calendar.set(Calendar.SECOND, toInt2(date, 10));
+ tzChar = 12;
+ }
+ else
+ {
+ calendar.set(Calendar.SECOND, 0);
+ }
+
+ calendar.set(Calendar.MILLISECOND, 0);
+
+ if (date[tzChar] != 'Z')
+ {
+ int hoursOff = 0;
+ int minutesOff = 0;
+
+ hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
+
+ if (date.length > tzChar + 3)
+ {
+ minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
+ }
+
+ if (date[tzChar] == '-')
+ {
+ return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
+ }
+ else
+ {
+ return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
+ }
+ }
+
+ return calendar.getTime();
+ }
+
+ static String getGeneralizedTimeDateString(Date date, boolean includeMillis)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ calendar.setTime(date);
+
+ String time = format4Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ + format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND));
+
+ if (includeMillis)
+ {
+ time += "." + format3(calendar.get(Calendar.MILLISECOND));
+ }
+
+ return time + "Z";
+ }
+
+ static Date fromGeneralizedTimeString(byte[] date)
+ {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ int year = toInt4(date, 0);
+
+ if (isLocalTime(date))
+ {
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+ }
+
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, toInt2(date, 4) - 1);
+ calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 6));
+ calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 8));
+ calendar.set(Calendar.MINUTE, toInt2(date, 10));
+
+ int tzChar = 12;
+
+ if (isNumber(date, tzChar))
+ {
+ calendar.set(Calendar.SECOND, toInt2(date, 12));
+ tzChar = 14;
+ }
+ else
+ {
+ calendar.set(Calendar.SECOND, 0);
+ }
+
+ if (tzChar != date.length && date[tzChar] == '.')
+ {
+ int millis = 0;
+ tzChar++;
+ if (isNumber(date, tzChar))
+ {
+ millis = (date[tzChar] - '0') * 100;
+ tzChar++;
+ }
+ if (tzChar != date.length && isNumber(date, tzChar))
+ {
+ millis += (date[tzChar] - '0') * 10;
+ tzChar++;
+ }
+ if (tzChar != date.length && isNumber(date, tzChar))
+ {
+ millis += (date[tzChar] - '0');
+ tzChar++;
+ }
+ calendar.set(Calendar.MILLISECOND, millis);
+ }
+ else
+ {
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+
+ // skip nano-seconds
+ while (tzChar != date.length && isNumber(date, tzChar))
+ {
+ tzChar++;
+ }
+
+ if (tzChar != date.length && date[tzChar] != 'Z')
+ {
+ int hoursOff = 0;
+ int minutesOff = 0;
+
+ hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
+
+ if (date.length > tzChar + 3)
+ {
+ minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
+ }
+
+ if (date[tzChar] == '-')
+ {
+ return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
+ }
+ else
+ {
+ return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
+ }
+ }
+
+ return calendar.getTime();
+ }
+
+ private static String format2(int v)
+ {
+ if (v < 10)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static String format2Year(int v)
+ {
+ if (v > 2000)
+ {
+ v = v - 2000;
+ }
+ else
+ {
+ v = v - 1900;
+ }
+
+ return format2(v);
+ }
+
+ private static String format3(int v)
+ {
+ if (v < 10)
+ {
+ return "00" + v;
+ }
+
+ if (v < 100)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static String format4Year(int v)
+ {
+ if (v < 10)
+ {
+ return "000" + v;
+ }
+
+ if (v < 100)
+ {
+ return "00" + v;
+ }
+
+ if (v < 1000)
+ {
+ return "0" + v;
+ }
+
+ return Integer.toString(v);
+ }
+
+ private static boolean isNumber(byte[] input, int off)
+ {
+ byte b = input[off];
+ return (b >= '0') && (b <= '9');
+ }
+
+ private static boolean isLocalTime(byte[] date)
+ {
+ for (int i = date.length - 1; i > date.length - 6; i--)
+ {
+ if (date[i] == 'Z' || date[i] == '-' || date[i] == '+')
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static int toInt2(byte[] input, int off)
+ {
+ return (input[off] - '0') * 10 + (input[off + 1] - '0');
+ }
+
+ private static int toInt4(byte[] input, int off)
+ {
+ return toInt2(input, off) * 100 + toInt2(input, off + 2) ;
+ }
+}
diff --git a/crypto/j2me/org/bouncycastle/asn1/StreamUtil.java b/crypto/j2me/org/bouncycastle/asn1/StreamUtil.java
index 6bc9914a0..67e3c2080 100644
--- a/crypto/j2me/org/bouncycastle/asn1/StreamUtil.java
+++ b/crypto/j2me/org/bouncycastle/asn1/StreamUtil.java
@@ -1,7 +1,6 @@
package org.bouncycastle.asn1;
import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/crypto/j2me/org/bouncycastle/asn1/cms/Time.java b/crypto/j2me/org/bouncycastle/asn1/cms/Time.java
index 1668d78f0..5bbbd339e 100644
--- a/crypto/j2me/org/bouncycastle/asn1/cms/Time.java
+++ b/crypto/j2me/org/bouncycastle/asn1/cms/Time.java
@@ -1,21 +1,30 @@
package org.bouncycastle.asn1.cms;
-import org.bouncycastle.asn1.*;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.bouncycastle.asn1.ASN1Choice;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.asn1.DERUTCTime;
public class Time
- implements DEREncodable, ASN1Choice
+ extends ASN1Object
+ implements ASN1Choice
{
- DERObject time;
+ ASN1Primitive time;
public static Time getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
- return getInstance(obj.getObject());
+ return getInstance(obj.getObject()); // must be explicitly tagged
}
public Time(
- DERObject time)
+ ASN1Primitive time)
{
if (!(time instanceof DERUTCTime)
&& !(time instanceof DERGeneralizedTime))
@@ -26,6 +35,30 @@ public class Time
this.time = time;
}
+ /**
+ * 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.
+ */
+ public Time(
+ Date date)
+ {
+ Calendar calendar = Calendar.getInstance();
+
+ calendar.setTime(date);
+
+ int year = calendar.get(Calendar.YEAR);
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DERGeneralizedTime(date);
+ }
+ else
+ {
+ time = new DERUTCTime(date);
+ }
+ }
+
public static Time getInstance(
Object obj)
{
@@ -42,7 +75,7 @@ public class Time
return new Time((DERGeneralizedTime)obj);
}
- throw new IllegalArgumentException("unknown object in factory");
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
public String getTime()
@@ -57,15 +90,33 @@ public class Time
}
}
+ public Date getDate()
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getDate();
+ }
+ }
+
/**
+ * Produce an object suitable for an ASN1OutputStream.
* <pre>
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*/
- public DERObject getDERObject()
+ public ASN1Primitive toASN1Primitive()
{
return time;
}
+
+ public String toString()
+ {
+ return getTime();
+ }
}
diff --git a/crypto/j2me/org/bouncycastle/asn1/eac/PackedDate.java b/crypto/j2me/org/bouncycastle/asn1/eac/PackedDate.java
new file mode 100644
index 000000000..2259eb894
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/asn1/eac/PackedDate.java
@@ -0,0 +1,70 @@
+package org.bouncycastle.asn1.eac;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * EAC encoding date object
+ */
+public class PackedDate
+{
+ private byte[] time;
+
+ public PackedDate(
+ String time)
+ {
+ this.time = convert(time);
+ }
+
+ private byte[] convert(String sTime)
+ {
+ char[] digs = sTime.toCharArray();
+ byte[] date = new byte[6];
+
+ for (int i = 0; i != 6; i++)
+ {
+ date[i] = (byte)(digs[i] - '0');
+ }
+
+ return date;
+ }
+
+ PackedDate(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PackedDate))
+ {
+ return false;
+ }
+
+ PackedDate other = (PackedDate)o;
+
+ return Arrays.areEqual(time, other.time);
+ }
+
+ public String toString()
+ {
+ char[] dateC = new char[time.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)((time[i] & 0xff) + '0');
+ }
+
+ return new String(dateC);
+ }
+
+ public byte[] getEncoding()
+ {
+ return time;
+ }
+}
diff --git a/crypto/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java b/crypto/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
new file mode 100644
index 000000000..22844c298
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/asn1/test/GeneralizedTimeTest.java
@@ -0,0 +1,189 @@
+package org.bouncycastle.asn1.test;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.bouncycastle.asn1.ASN1GeneralizedTime;
+import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class GeneralizedTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "20020122122220",
+ "20020122122220Z",
+ "20020122122220-1000",
+ "20020122122220+00",
+ "20020122122220.1",
+ "20020122122220.1Z",
+ "20020122122220.1-1000",
+ "20020122122220.1+00",
+ "20020122122220.01",
+ "20020122122220.01Z",
+ "20020122122220.01-1000",
+ "20020122122220.01+00",
+ "20020122122220.001",
+ "20020122122220.001Z",
+ "20020122122220.001-1000",
+ "20020122122220.001+00",
+ "20020122122220.0001",
+ "20020122122220.0001Z",
+ "20020122122220.0001-1000",
+ "20020122122220.0001+00",
+ "20020122122220.0001+1000"
+ };
+
+ String[] output = {
+ "20020122122220",
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+00:00",
+ "20020122122220.1",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.1GMT-10:00",
+ "20020122122220.1GMT+00:00",
+ "20020122122220.01",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.01GMT-10:00",
+ "20020122122220.01GMT+00:00",
+ "20020122122220.001",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.001GMT-10:00",
+ "20020122122220.001GMT+00:00",
+ "20020122122220.0001",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT-10:00",
+ "20020122122220.0001GMT+00:00",
+ "20020122122220.0001GMT+10:00" };
+
+ String[] zOutput = {
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122122220Z",
+ "20020122022220Z"
+ };
+
+ String[] mzOutput = {
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122122220.100Z",
+ "20020122122220.100Z",
+ "20020122222220.100Z",
+ "20020122122220.100Z",
+ "20020122122220.010Z",
+ "20020122122220.010Z",
+ "20020122222220.010Z",
+ "20020122122220.010Z",
+ "20020122122220.001Z",
+ "20020122122220.001Z",
+ "20020122222220.001Z",
+ "20020122122220.001Z",
+ "20020122122220.000Z",
+ "20020122122220.000Z",
+ "20020122222220.000Z",
+ "20020122122220.000Z",
+ "20020122022220.000Z"
+ };
+
+ public String getName()
+ {
+ return "GeneralizedTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+ for (int i = 0; i != input.length; i++)
+ {
+ DERGeneralizedTime t = new DERGeneralizedTime(input[i]);
+
+ if (output[i].indexOf('G') > 0) // don't check local time the same way
+ {
+ if (!t.getTime().equals(output[i]))
+ {
+ fail("failed conversion test");
+ }
+ }
+ else
+ {
+ String offset = calculateGMTOffset(t.getDate());
+
+ if (!t.getTime().equals(output[i] + offset))
+ {
+ fail("failed conversion test");
+ }
+ }
+ }
+
+ for (int i = 0; i != input.length; i++)
+ {
+ ASN1GeneralizedTime t = new ASN1GeneralizedTime(mzOutput[i]);
+
+ if (!new ASN1GeneralizedTime(t.getDate(), true).getDate().equals(t.getDate()))
+ {
+ fail("failed equality test");
+ }
+ }
+ }
+
+ private String calculateGMTOffset(Date date)
+ {
+ 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);
+
+// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(date))
+// {
+// hours += sign.equals("+") ? 1 : -1;
+// }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new GeneralizedTimeTest());
+ }
+}
diff --git a/crypto/j2me/org/bouncycastle/asn1/test/RegressionTest.java b/crypto/j2me/org/bouncycastle/asn1/test/RegressionTest.java
index dbaa5b348..e1a9f9bc4 100644
--- a/crypto/j2me/org/bouncycastle/asn1/test/RegressionTest.java
+++ b/crypto/j2me/org/bouncycastle/asn1/test/RegressionTest.java
@@ -6,17 +6,68 @@ import org.bouncycastle.util.test.TestResult;
public class RegressionTest
{
public static Test[] tests = {
+ new EqualsAndHashCodeTest(),
+ new TagTest(),
+ new SetTest(),
+ new DERUTF8StringTest(),
new CertificateTest(),
+ new GenerationTest(),
new CMSTest(),
new OCSPTest(),
new OIDTest(),
new PKCS10Test(),
new PKCS12Test(),
new X509NameTest(),
+ new X500NameTest(),
+ new X509ExtensionsTest(),
+ new GeneralizedTimeTest(),
new BitStringTest(),
new MiscTest(),
+ new SMIMETest(),
new X9Test(),
- new EncryptedPrivateKeyInfoTest()
+ new MonetaryValueUnitTest(),
+ new BiometricDataUnitTest(),
+ new Iso4217CurrencyCodeUnitTest(),
+ new SemanticsInformationUnitTest(),
+ new QCStatementUnitTest(),
+ new TypeOfBiometricDataUnitTest(),
+ new SignerLocationUnitTest(),
+ new CommitmentTypeQualifierUnitTest(),
+ new CommitmentTypeIndicationUnitTest(),
+ new EncryptedPrivateKeyInfoTest(),
+ new DataGroupHashUnitTest(),
+ new LDSSecurityObjectUnitTest(),
+ new AttributeTableUnitTest(),
+ new ReasonFlagsTest(),
+ new NetscapeCertTypeTest(),
+ new PKIFailureInfoTest(),
+ new KeyUsageTest(),
+ new StringTest(),
+ new UTCTimeTest(),
+ new RequestedCertificateUnitTest(),
+ new OtherCertIDUnitTest(),
+ new OtherSigningCertificateUnitTest(),
+ new ContentHintsUnitTest(),
+ new CertHashUnitTest(),
+ new AdditionalInformationSyntaxUnitTest(),
+ new AdmissionSyntaxUnitTest(),
+ new AdmissionsUnitTest(),
+ new DeclarationOfMajorityUnitTest(),
+ new ProcurationSyntaxUnitTest(),
+ new ProfessionInfoUnitTest(),
+ new RestrictionUnitTest(),
+ new NamingAuthorityUnitTest(),
+ new MonetaryLimitUnitTest(),
+ new NameOrPseudonymUnitTest(),
+ new PersonalDataUnitTest(),
+ new DERApplicationSpecificTest(),
+ new IssuingDistributionPointUnitTest(),
+ new TargetInformationTest(),
+ new SubjectKeyIdentifierTest(),
+ new ESSCertIDv2UnitTest(),
+ new ParsingTest(),
+ new GeneralNameTest(),
+ new RFC4519Test()
};
public static void main(
@@ -25,6 +76,12 @@ public class RegressionTest
for (int i = 0; i != tests.length; i++)
{
TestResult result = tests[i].perform();
+
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace();
+ }
+
System.out.println(result);
}
}
diff --git a/crypto/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java b/crypto/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java
new file mode 100644
index 000000000..e25bd9cd0
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/asn1/test/UTCTimeTest.java
@@ -0,0 +1,98 @@
+package org.bouncycastle.asn1.test;
+
+import org.bouncycastle.asn1.ASN1UTCTime;
+import org.bouncycastle.asn1.DERUTCTime;
+import org.bouncycastle.util.test.SimpleTest;
+
+/**
+ * X.690 test example
+ */
+public class UTCTimeTest
+ extends SimpleTest
+{
+ String[] input =
+ {
+ "020122122220Z",
+ "020122122220-1000",
+ "020122122220+1000",
+ "020122122220+00",
+ "0201221222Z",
+ "0201221222-1000",
+ "0201221222+1000",
+ "0201221222+00",
+ "550122122220Z",
+ "5501221222Z"
+ };
+
+ String[] output = {
+ "20020122122220GMT+00:00",
+ "20020122122220GMT-10:00",
+ "20020122122220GMT+10:00",
+ "20020122122220GMT+00:00",
+ "20020122122200GMT+00:00",
+ "20020122122200GMT-10:00",
+ "20020122122200GMT+10:00",
+ "20020122122200GMT+00:00",
+ "19550122122220GMT+00:00",
+ "19550122122200GMT+00:00"
+ };
+
+ String[] zOutput1 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ String[] zOutput2 = {
+ "20020122122220Z",
+ "20020122222220Z",
+ "20020122022220Z",
+ "20020122122220Z",
+ "20020122122200Z",
+ "20020122222200Z",
+ "20020122022200Z",
+ "20020122122200Z",
+ "19550122122220Z",
+ "19550122122200Z"
+ };
+
+ public String getName()
+ {
+ return "UTCTime";
+ }
+
+ public void performTest()
+ throws Exception
+ {
+
+ for (int i = 0; i != input.length; i++)
+ {
+ DERUTCTime t = new DERUTCTime(input[i]);
+
+ if (!t.getAdjustedTime().equals(output[i]))
+ {
+ fail("failed conversion test " + i);
+ }
+
+ t = new ASN1UTCTime(zOutput1[i].substring(2));
+
+ if (!new ASN1UTCTime(t.getAdjustedDate()).getAdjustedTime().equals(t.getAdjustedTime()))
+ {
+ fail("failed equality test");
+ }
+ }
+ }
+
+ public static void main(
+ String[] args)
+ {
+ runTest(new UTCTimeTest());
+ }
+}
diff --git a/crypto/j2me/org/bouncycastle/asn1/x509/Time.java b/crypto/j2me/org/bouncycastle/asn1/x509/Time.java
index 14da1dc5a..f8ca4e203 100644
--- a/crypto/j2me/org/bouncycastle/asn1/x509/Time.java
+++ b/crypto/j2me/org/bouncycastle/asn1/x509/Time.java
@@ -1,21 +1,30 @@
package org.bouncycastle.asn1.x509;
-import org.bouncycastle.asn1.*;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.bouncycastle.asn1.ASN1Choice;
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.asn1.DERUTCTime;
public class Time
- implements DEREncodable, ASN1Choice
+ extends ASN1Object
+ implements ASN1Choice
{
- DERObject time;
+ ASN1Primitive time;
public static Time getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
- return getInstance(obj.getObject());
+ return getInstance(obj.getObject()); // must be explicitly tagged
}
public Time(
- DERObject time)
+ ASN1Primitive time)
{
if (!(time instanceof DERUTCTime)
&& !(time instanceof DERGeneralizedTime))
@@ -26,6 +35,30 @@ public class Time
this.time = time;
}
+ /**
+ * 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.
+ */
+ public Time(
+ Date date)
+ {
+ Calendar calendar = Calendar.getInstance();
+
+ calendar.setTime(date);
+
+ int year = calendar.get(Calendar.YEAR);
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DERGeneralizedTime(date);
+ }
+ else
+ {
+ time = new DERUTCTime(date);
+ }
+ }
+
public static Time getInstance(
Object obj)
{
@@ -42,7 +75,7 @@ public class Time
return new Time((DERGeneralizedTime)obj);
}
- throw new IllegalArgumentException("unknown object in factory");
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
public String getTime()
@@ -57,15 +90,33 @@ public class Time
}
}
+ public Date getDate()
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getDate();
+ }
+ }
+
/**
+ * Produce an object suitable for an ASN1OutputStream.
* <pre>
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*/
- public DERObject getDERObject()
+ public ASN1Primitive toASN1Primitive()
{
return time;
}
+
+ public String toString()
+ {
+ return getTime();
+ }
}
diff --git a/crypto/j2me/org/bouncycastle/crypto/test/RSATest.java b/crypto/j2me/org/bouncycastle/crypto/test/RSATest.java
index b4b20fd01..2369d1c58 100644
--- a/crypto/j2me/org/bouncycastle/crypto/test/RSATest.java
+++ b/crypto/j2me/org/bouncycastle/crypto/test/RSATest.java
@@ -3,22 +3,23 @@ package org.bouncycastle.crypto.test;
import java.math.BigInteger;
import java.security.SecureRandom;
-import org.bouncycastle.util.test.*;
-
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.engines.RSAEngine;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.encodings.OAEPEncoding;
+import org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
-
+import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.test.SimpleTest;
public class RSATest
- implements Test
+ extends SimpleTest
{
static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
static BigInteger pubExp = new BigInteger("11", 16);
@@ -35,22 +36,117 @@ public class RSATest
// to check that we handling byte extension by big number correctly.
//
static String edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+ static byte[] oversizedSig = Hex.decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] dudBlock = Hex.decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] truncatedDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] incorrectPadding = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+ static byte[] missingDataBlock = Hex.decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
public String getName()
{
return "RSA";
}
- public TestResult perform()
+ private void testStrictPKCS1Length(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
{
- RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
- RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
- byte[] data = Hex.decode(edgeInput);
+ AsymmetricBlockCipher eng = new RSAEngine();
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(oversizedSig, 0, oversizedSig.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("oversized signature block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals("block incorrect size"))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testTruncatedPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+ }
+
+ private void testDudPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+ }
+
+ private void testWrongPaddingPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+ }
+
+ private void testMissingDataPKCS1Block(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
+ checkForPKCS1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+ }
+
+ private void checkForPKCS1Exception(RSAKeyParameters pubParameters, RSAKeyParameters privParameters, byte[] inputData, String expectedMessage)
+ {
+ AsymmetricBlockCipher eng = new RSAEngine();
+
+ eng.init(true, privParameters);
+
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(inputData, 0, inputData.length);
+ }
+ catch (Exception e)
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+
+ eng = new PKCS1Encoding(eng);
+
+ eng.init(false, pubParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+
+ fail("missing data block not recognised");
+ }
+ catch (InvalidCipherTextException e)
+ {
+ if (!e.getMessage().equals(expectedMessage))
+ {
+ fail("RSA: failed - exception " + e.toString(), e);
+ }
+ }
+ }
+
+ private void testOAEP(RSAKeyParameters pubParameters, RSAKeyParameters privParameters)
+ {
//
- // RAW
+ // OAEP - public encrypt, private decrypt
//
- AsymmetricBlockCipher eng = new RSAEngine();
+ AsymmetricBlockCipher eng = new OAEPEncoding(new RSAEngine());
+ byte[] data = Hex.decode(input);
eng.init(true, pubParameters);
@@ -60,7 +156,7 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
eng.init(false, privParameters);
@@ -71,15 +167,65 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
- if (!edgeInput.equals(new String(Hex.encode(data))))
+ if (!input.equals(new String(Hex.encode(data))))
+ {
+ fail("failed OAEP Test");
+ }
+ }
+
+ private void zeroBlockTest(CipherParameters encParameters, CipherParameters decParameters)
+ {
+ AsymmetricBlockCipher eng = new PKCS1Encoding(new RSAEngine());
+
+ eng.init(true, encParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
{
- return new SimpleTestResult(false, "RSA: failed RAW edge Test");
+ fail("PKCS1 output block size incorrect");
}
- data = Hex.decode(input);
+ byte[] zero = new byte[0];
+ byte[] data = null;
+
+ try
+ {
+ data = eng.processBlock(zero, 0, zero.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ eng.init(false, decParameters);
+
+ try
+ {
+ data = eng.processBlock(data, 0, data.length);
+ }
+ catch (Exception e)
+ {
+ fail("failed - exception " + e.toString(), e);
+ }
+
+ if (!Arrays.areEqual(zero, data))
+ {
+ fail("failed PKCS1 zero Test");
+ }
+ }
+
+ public void performTest()
+ {
+ RSAKeyParameters pubParameters = new RSAKeyParameters(false, mod, pubExp);
+ RSAKeyParameters privParameters = new RSAPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+ byte[] data = Hex.decode(edgeInput);
+
+ //
+ // RAW
+ //
+ AsymmetricBlockCipher eng = new RSAEngine();
eng.init(true, pubParameters);
@@ -89,7 +235,7 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("RSA: failed - exception " + e.toString(), e);
}
eng.init(false, privParameters);
@@ -100,18 +246,15 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
- if (!input.equals(new String(Hex.encode(data))))
+ if (!edgeInput.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed RAW Test");
+ fail("failed RAW edge Test");
}
- //
- // PKCS1 - public encrypt, private decrypt
- //
- eng = new PKCS1Encoding(eng);
+ data = Hex.decode(input);
eng.init(true, pubParameters);
@@ -121,7 +264,7 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
eng.init(false, privParameters);
@@ -132,20 +275,25 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
if (!input.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed PKCS1 public/private Test");
+ fail("failed RAW Test");
}
//
- // PKCS1 - private encrypt, public decrypt
+ // PKCS1 - public encrypt, private decrypt
//
- eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
+ eng = new PKCS1Encoding(eng);
- eng.init(true, privParameters);
+ eng.init(true, pubParameters);
+
+ if (eng.getOutputBlockSize() != ((PKCS1Encoding)eng).getUnderlyingCipher().getOutputBlockSize())
+ {
+ fail("PKCS1 output block size incorrect");
+ }
try
{
@@ -153,10 +301,10 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
- eng.init(false, pubParameters);
+ eng.init(false, privParameters);
try
{
@@ -164,20 +312,20 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
if (!input.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed PKCS1 private/public Test");
+ fail("failed PKCS1 public/private Test");
}
//
- // OAEP - public encrypt, private decrypt
+ // PKCS1 - private encrypt, public decrypt
//
- eng = new OAEPEncoding(((PKCS1Encoding)eng).getUnderlyingCipher());
+ eng = new PKCS1Encoding(((PKCS1Encoding)eng).getUnderlyingCipher());
- eng.init(true, pubParameters);
+ eng.init(true, privParameters);
try
{
@@ -185,10 +333,10 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
- eng.init(false, privParameters);
+ eng.init(false, pubParameters);
try
{
@@ -196,14 +344,20 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
if (!input.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed OAEP Test");
+ fail("failed PKCS1 private/public Test");
}
+ zeroBlockTest(pubParameters, privParameters);
+ zeroBlockTest(privParameters, pubParameters);
+
+ //
+ // key generation test
+ //
RSAKeyPairGenerator pGen = new RSAKeyPairGenerator();
RSAKeyGenerationParameters genParam = new RSAKeyGenerationParameters(
BigInteger.valueOf(0x11), new SecureRandom(), 768, 25);
@@ -214,9 +368,9 @@ public class RSATest
eng = new RSAEngine();
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 762)
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 768)
{
- return new SimpleTestResult(false, "RSA: failed key generation (768) length test");
+ fail("failed key generation (768) length test");
}
eng.init(true, pair.getPublic());
@@ -227,7 +381,7 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
eng.init(false, pair.getPrivate());
@@ -238,12 +392,12 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
if (!input.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed key generation (768) Test");
+ fail("failed key generation (768) Test");
}
genParam = new RSAKeyGenerationParameters(BigInteger.valueOf(0x11), new SecureRandom(), 1024, 25);
@@ -253,9 +407,9 @@ public class RSATest
eng.init(true, pair.getPublic());
- if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1018)
+ if (((RSAKeyParameters)pair.getPublic()).getModulus().bitLength() < 1024)
{
- return new SimpleTestResult(false, "RSA: failed key generation (1024) length test");
+ fail("failed key generation (1024) length test");
}
try
@@ -264,7 +418,7 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
eng.init(false, pair.getPrivate());
@@ -275,23 +429,52 @@ public class RSATest
}
catch (Exception e)
{
- return new SimpleTestResult(false, "RSA: failed - exception " + e.toString());
+ fail("failed - exception " + e.toString(), e);
}
if (!input.equals(new String(Hex.encode(data))))
{
- return new SimpleTestResult(false, "RSA: failed key generation (1024) test");
+ fail("failed key generation (1024) test");
}
- return new SimpleTestResult(false, "RSA: Okay");
+ genParam = new RSAKeyGenerationParameters(
+ BigInteger.valueOf(0x11), new SecureRandom(), 16, 25);
+ pGen.init(genParam);
+
+ for (int i = 0; i < 100; ++i)
+ {
+ pair = pGen.generateKeyPair();
+ RSAPrivateCrtKeyParameters privKey = (RSAPrivateCrtKeyParameters) pair.getPrivate();
+ BigInteger pqDiff = privKey.getP().subtract(privKey.getQ()).abs();
+
+ if (pqDiff.bitLength() < 5)
+ {
+ fail("P and Q too close in RSA key pair");
+ }
+ }
+
+ testOAEP(pubParameters, privParameters);
+ testStrictPKCS1Length(pubParameters, privParameters);
+ testDudPKCS1Block(pubParameters, privParameters);
+ testMissingDataPKCS1Block(pubParameters, privParameters);
+ testTruncatedPKCS1Block(pubParameters, privParameters);
+ testWrongPaddingPKCS1Block(pubParameters, privParameters);
+
+ try
+ {
+ new RSAEngine().processBlock(new byte[]{ 1 }, 0, 1);
+ fail("failed initialisation check");
+ }
+ catch (IllegalStateException e)
+ {
+ // expected
+ }
}
+
public static void main(
String[] args)
{
- RSATest test = new RSATest();
- TestResult result = test.perform();
-
- System.out.println(result);
+ runTest(new RSATest());
}
}
diff --git a/crypto/j2me/org/bouncycastle/crypto/test/RegressionTest.java b/crypto/j2me/org/bouncycastle/crypto/test/RegressionTest.java
index d34638a8d..f8d37aaa1 100644
--- a/crypto/j2me/org/bouncycastle/crypto/test/RegressionTest.java
+++ b/crypto/j2me/org/bouncycastle/crypto/test/RegressionTest.java
@@ -1,15 +1,11 @@
package org.bouncycastle.crypto.test;
-import org.bouncycastle.crypto.test.GOST28147Test;
-import org.bouncycastle.crypto.test.GOST3410Test;
-import org.bouncycastle.util.test.*;
+import org.bouncycastle.util.test.Test;
+import org.bouncycastle.util.test.TestResult;
public final class RegressionTest
{
- private RegressionTest()
- { };
-
- private static Test[] _tests = {
+ public static Test[] tests = {
new AESTest(),
new DESTest(),
new DESedeTest(),
@@ -62,9 +58,9 @@ public final class RegressionTest
public static void main(
String[] args)
{
- for (int i = 0; i != _tests.length; i++)
+ for (int i = 0; i != tests.length; i++)
{
- TestResult result = _tests[i].perform();
+ TestResult result = tests[i].perform();
System.out.println(result);
}
}
diff --git a/crypto/j2me/org/bouncycastle/util/Selector.java b/crypto/j2me/org/bouncycastle/util/Selector.java
new file mode 100644
index 000000000..79a1dd82a
--- /dev/null
+++ b/crypto/j2me/org/bouncycastle/util/Selector.java
@@ -0,0 +1,8 @@
+package org.bouncycastle.util;
+
+public interface Selector
+{
+ boolean match(Object obj);
+
+ Object clone();
+}