+ * One entry: [FIELDTYPE(FT)][FIELDSIZE(FS)][FIELDDATA(FD)] + * [FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)][FT+FS+(FD)]... + * + * [ 2 bytes] FIELDTYPE + * [ 4 bytes] FIELDSIZE, size of FIELDDATA in bytes + * [ n bytes] FIELDDATA, n = FIELDSIZE + * + * Notes: + * - Strings are stored in UTF-8 encoded form and are null-terminated. + * - FIELDTYPE can be one of the FT_ constants. + *+ * + * @author Naomaru Itoi
+ * The cipher must be initialized for the requested operation before being used + * by a {@code BetterCipherInputStream}. For example, if a cipher initialized for + * decryption is used with a {@code BetterCipherInputStream}, the {@code + * BetterCipherInputStream} tries to read the data an decrypt them before returning. + */ +public class BetterCipherInputStream extends FilterInputStream { + + private final Cipher cipher; + private static final int I_DEFAULT_BUFFER_SIZE = 8 * 1024; + private final byte[] i_buffer; + private int index; // index of the bytes to return from o_buffer + private byte[] o_buffer; + private boolean finished; + + /** + * Creates a new {@code BetterCipherInputStream} instance for an {@code + * InputStream} and a cipher. + * + * @param is + * the input stream to read data from. + * @param c + * the cipher to process the data with. + */ + public BetterCipherInputStream(InputStream is, Cipher c) { + this(is, c, I_DEFAULT_BUFFER_SIZE); + } + + /** + * Creates a new {@code BetterCipherInputStream} instance for an {@code + * InputStream} and a cipher. + * + * @param is + * the input stream to read data from. + * @param c + * the cipher to process the data with. + * @param bufferSize + * size to buffer output from the cipher + */ + public BetterCipherInputStream(InputStream is, Cipher c, int bufferSize) { + super(is); + this.cipher = c; + i_buffer = new byte[bufferSize]; + } + + /** + * Creates a new {@code BetterCipherInputStream} instance for an {@code + * InputStream} without a cipher. + *
+ * A {@code NullCipher} is created and used to process the data. + * + * @param is + * the input stream to read data from. + */ + protected BetterCipherInputStream(InputStream is) { + this(is, new NullCipher()); + } + + /** + * Reads the next byte from this cipher input stream. + * + * @return the next byte, or {@code -1} if the end of the stream is reached. + * @throws IOException + * if an error occurs. + */ + @Override + public int read() throws IOException { + if (finished) { + return ((o_buffer == null) || (index == o_buffer.length)) + ? -1 + : o_buffer[index++] & 0xFF; + } + if ((o_buffer != null) && (index < o_buffer.length)) { + return o_buffer[index++] & 0xFF; + } + index = 0; + o_buffer = null; + int num_read; + while (o_buffer == null) { + if ((num_read = in.read(i_buffer)) == -1) { + try { + o_buffer = cipher.doFinal(); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + finished = true; + break; + } + o_buffer = cipher.update(i_buffer, 0, num_read); + } + return read(); + } + + /** + * Reads the next {@code b.length} bytes from this input stream into buffer + * {@code b}. + * + * @param b + * the buffer to be filled with data. + * @return the number of bytes filled into buffer {@code b}, or {@code -1} + * if the end of the stream is reached. + * @throws IOException + * if an error occurs. + */ + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + /** + * Reads the next {@code len} bytes from this input stream into buffer + * {@code b} starting at offset {@code off}. + *
+ * if {@code b} is {@code null}, the next {@code len} bytes are read and
+ * discarded.
+ *
+ * @param b
+ * the buffer to be filled with data.
+ * @param off
+ * the offset to start in the buffer.
+ * @param len
+ * the maximum number of bytes to read.
+ * @return the number of bytes filled into buffer {@code b}, or {@code -1}
+ * of the of the stream is reached.
+ * @throws IOException
+ * if an error occurs.
+ * @throws NullPointerException
+ * if the underlying input stream is {@code null}.
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (in == null) {
+ throw new NullPointerException("Underlying input stream is null");
+ }
+
+ int read_b;
+ int i;
+ for (i=0; i
+ * A map iterator is an efficient way of iterating over maps.
+ * There is no need to access the entry set or cast to Map Entry objects.
+ *
+ * A map iterator is an efficient way of iterating over maps.
+ * There is no need to access the entry set or cast to Map Entry objects.
+ *
+ * A Map Entry has considerable additional semantics over and above a simple
+ * key-value pair. This interface defines the minimum key value, with just the
+ * two get methods.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public interface KeyValue {
+
+ /**
+ * Gets the key from the pair.
+ *
+ * @return the key
+ */
+ Object getKey();
+
+ /**
+ * Gets the value from the pair.
+ *
+ * @return the value
+ */
+ Object getValue();
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/MapIterator.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/MapIterator.java
new file mode 100644
index 00000000..cc100e97
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/MapIterator.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.Iterator;
+
+/**
+ * Defines an iterator that operates over a
+ * This iterator is a special version designed for maps. It can be more
+ * efficient to use this rather than an entry set iterator where the option
+ * is available, and it is certainly more convenient.
+ *
+ * A map that provides this interface may not hold the data internally using
+ * Map Entry objects, thus this interface can avoid lots of object creation.
+ *
+ * In use, this iterator iterates through the keys in the map. After each call
+ * to
+ * This method can be called once per call to
+ * This interface allows an iterator to be repeatedly reused.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public interface ResettableIterator extends Iterator {
+
+ /**
+ * Resets the iterator back to the position at which the iterator
+ * was created.
+ */
+ public void reset();
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/AbstractEmptyIterator.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/AbstractEmptyIterator.java
new file mode 100644
index 00000000..1d90ad59
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/AbstractEmptyIterator.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.iterators;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Provides an implementation of an empty iterator.
+ *
+ * @since Commons Collections 3.1
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+abstract class AbstractEmptyIterator {
+
+ /**
+ * Constructor.
+ */
+ protected AbstractEmptyIterator() {
+ super();
+ }
+
+ public boolean hasNext() {
+ return false;
+ }
+
+ public Object next() {
+ throw new NoSuchElementException("Iterator contains no elements");
+ }
+
+ public boolean hasPrevious() {
+ return false;
+ }
+
+ public Object previous() {
+ throw new NoSuchElementException("Iterator contains no elements");
+ }
+
+ public int nextIndex() {
+ return 0;
+ }
+
+ public int previousIndex() {
+ return -1;
+ }
+
+ public void add(Object obj) {
+ throw new UnsupportedOperationException("add() not supported for empty Iterator");
+ }
+
+ public void set(Object obj) {
+ throw new IllegalStateException("Iterator contains no elements");
+ }
+
+ public void remove() {
+ throw new IllegalStateException("Iterator contains no elements");
+ }
+
+ public Object getKey() {
+ throw new IllegalStateException("Iterator contains no elements");
+ }
+
+ public Object getValue() {
+ throw new IllegalStateException("Iterator contains no elements");
+ }
+
+ public Object setValue(Object value) {
+ throw new IllegalStateException("Iterator contains no elements");
+ }
+
+ public void reset() {
+ // do nothing
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyIterator.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyIterator.java
new file mode 100644
index 00000000..1685bfb6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyIterator.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.iterators;
+
+import java.util.Iterator;
+
+import org.apache.commons.collections.ResettableIterator;
+
+/**
+ * Provides an implementation of an empty iterator.
+ *
+ * This class provides an implementation of an empty iterator.
+ * This class provides for binary compatability between Commons Collections
+ * 2.1.1 and 3.1 due to issues with
+ * This
+ * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)}
+ *
+ * @param obj the object to compare to
+ * @return true if equal key and value
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Map.Entry == false) {
+ return false;
+ }
+ Map.Entry other = (Map.Entry) obj;
+ return
+ (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
+ (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
+ }
+
+ /**
+ * Gets a hashCode compatible with the equals method.
+ *
+ * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()}
+ *
+ * @return a suitable hash code
+ */
+ public int hashCode() {
+ return (getKey() == null ? 0 : getKey().hashCode()) ^
+ (getValue() == null ? 0 : getValue().hashCode());
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/DefaultMapEntry.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/DefaultMapEntry.java
new file mode 100644
index 00000000..cff540b7
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/DefaultMapEntry.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import java.util.Map;
+
+import org.apache.commons.collections.KeyValue;
+
+/**
+ * A restricted implementation of {@link java.util.Map.Entry} that prevents
+ * the
+ * This class implements all the features necessary for a subclass hash-based map.
+ * Key-value entries are stored in instances of the
+ * Overridable methods are provided to change the default hashing behaviour, and
+ * to change how entries are added to and removed from the map. Hopefully, all you
+ * need for unusual subclasses is here.
+ *
+ * NOTE: From Commons Collections 3.1 this class extends AbstractMap.
+ * This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1.
+ * This extends clause will be removed in v4.0.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author java util HashMap
+ * @author Stephen Colebourne
+ * @author Christian Siefkes
+ */
+public class AbstractHashedMap extends AbstractMap implements IterableMap {
+
+ protected static final String NO_NEXT_ENTRY = "No next() entry in the iteration";
+ protected static final String NO_PREVIOUS_ENTRY = "No previous() entry in the iteration";
+ protected static final String REMOVE_INVALID = "remove() can only be called once after next()";
+ protected static final String GETKEY_INVALID = "getKey() can only be called after next() and before remove()";
+ protected static final String GETVALUE_INVALID = "getValue() can only be called after next() and before remove()";
+ protected static final String SETVALUE_INVALID = "setValue() can only be called after next() and before remove()";
+
+ /** The default capacity to use */
+ protected static final int DEFAULT_CAPACITY = 16;
+ /** The default threshold to use */
+ protected static final int DEFAULT_THRESHOLD = 12;
+ /** The default load factor to use */
+ protected static final float DEFAULT_LOAD_FACTOR = 0.75f;
+ /** The maximum capacity allowed */
+ protected static final int MAXIMUM_CAPACITY = 1 << 30;
+ /** An object for masking null */
+ protected static final Object NULL = new Object();
+
+ /** Load factor, normally 0.75 */
+ protected transient float loadFactor;
+ /** The size of the map */
+ protected transient int size;
+ /** Map entries */
+ protected transient HashEntry[] data;
+ /** Size at which to rehash */
+ protected transient int threshold;
+ /** Modification count for iterators */
+ protected transient int modCount;
+ /** Entry set */
+ protected transient EntrySet entrySet;
+ /** Key set */
+ protected transient KeySet keySet;
+ /** Values */
+ protected transient Values values;
+
+ /**
+ * Constructor only used in deserialization, do not use otherwise.
+ */
+ protected AbstractHashedMap() {
+ super();
+ }
+
+ /**
+ * Constructor which performs no validation on the passed in parameters.
+ *
+ * @param initialCapacity the initial capacity, must be a power of two
+ * @param loadFactor the load factor, must be > 0.0f and generally < 1.0f
+ * @param threshold the threshold, must be sensible
+ */
+ protected AbstractHashedMap(int initialCapacity, float loadFactor, int threshold) {
+ super();
+ this.loadFactor = loadFactor;
+ this.data = new HashEntry[initialCapacity];
+ this.threshold = threshold;
+ init();
+ }
+
+ /**
+ * Constructs a new, empty map with the specified initial capacity and
+ * default load factor.
+ *
+ * @param initialCapacity the initial capacity
+ * @throws IllegalArgumentException if the initial capacity is less than one
+ */
+ protected AbstractHashedMap(int initialCapacity) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR);
+ }
+
+ /**
+ * Constructs a new, empty map with the specified initial capacity and
+ * load factor.
+ *
+ * @param initialCapacity the initial capacity
+ * @param loadFactor the load factor
+ * @throws IllegalArgumentException if the initial capacity is less than one
+ * @throws IllegalArgumentException if the load factor is less than or equal to zero
+ */
+ protected AbstractHashedMap(int initialCapacity, float loadFactor) {
+ super();
+ if (initialCapacity < 1) {
+ throw new IllegalArgumentException("Initial capacity must be greater than 0");
+ }
+ if (loadFactor <= 0.0f || Float.isNaN(loadFactor)) {
+ throw new IllegalArgumentException("Load factor must be greater than 0");
+ }
+ this.loadFactor = loadFactor;
+ initialCapacity = calculateNewCapacity(initialCapacity);
+ this.threshold = calculateThreshold(initialCapacity, loadFactor);
+ this.data = new HashEntry[initialCapacity];
+ init();
+ }
+
+ /**
+ * Constructor copying elements from another map.
+ *
+ * @param map the map to copy
+ * @throws NullPointerException if the map is null
+ */
+ protected AbstractHashedMap(Map map) {
+ this(Math.max(2 * map.size(), DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
+ putAll(map);
+ }
+
+ /**
+ * Initialise subclasses during construction, cloning or deserialization.
+ */
+ protected void init() {
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the value mapped to the key specified.
+ *
+ * @param key the key
+ * @return the mapped value, null if no match
+ */
+ public Object get(Object key) {
+ key = convertKey(key);
+ int hashCode = hash(key);
+ HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
+ while (entry != null) {
+ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
+ return entry.getValue();
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ /**
+ * Gets the size of the map.
+ *
+ * @return the size
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Checks whether the map is currently empty.
+ *
+ * @return true if the map is currently size zero
+ */
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether the map contains the specified key.
+ *
+ * @param key the key to search for
+ * @return true if the map contains the key
+ */
+ public boolean containsKey(Object key) {
+ key = convertKey(key);
+ int hashCode = hash(key);
+ HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
+ while (entry != null) {
+ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
+ return true;
+ }
+ entry = entry.next;
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether the map contains the specified value.
+ *
+ * @param value the value to search for
+ * @return true if the map contains the value
+ */
+ public boolean containsValue(Object value) {
+ if (value == null) {
+ for (int i = 0, isize = data.length; i < isize; i++) {
+ HashEntry entry = data[i];
+ while (entry != null) {
+ if (entry.getValue() == null) {
+ return true;
+ }
+ entry = entry.next;
+ }
+ }
+ } else {
+ for (int i = 0, isize = data.length; i < isize; i++) {
+ HashEntry entry = data[i];
+ while (entry != null) {
+ if (isEqualValue(value, entry.getValue())) {
+ return true;
+ }
+ entry = entry.next;
+ }
+ }
+ }
+ return false;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Puts a key-value mapping into this map.
+ *
+ * @param key the key to add
+ * @param value the value to add
+ * @return the value previously mapped to this key, null if none
+ */
+ public Object put(Object key, Object value) {
+ key = convertKey(key);
+ int hashCode = hash(key);
+ int index = hashIndex(hashCode, data.length);
+ HashEntry entry = data[index];
+ while (entry != null) {
+ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
+ Object oldValue = entry.getValue();
+ updateEntry(entry, value);
+ return oldValue;
+ }
+ entry = entry.next;
+ }
+
+ addMapping(index, hashCode, key, value);
+ return null;
+ }
+
+ /**
+ * Puts all the values from the specified map into this map.
+ *
+ * This implementation iterates around the specified map and
+ * uses {@link #put(Object, Object)}.
+ *
+ * @param map the map to add
+ * @throws NullPointerException if the map is null
+ */
+ public void putAll(Map map) {
+ int mapSize = map.size();
+ if (mapSize == 0) {
+ return;
+ }
+ int newSize = (int) ((size + mapSize) / loadFactor + 1);
+ ensureCapacity(calculateNewCapacity(newSize));
+ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Removes the specified mapping from this map.
+ *
+ * @param key the mapping to remove
+ * @return the value mapped to the removed key, null if key not in map
+ */
+ public Object remove(Object key) {
+ key = convertKey(key);
+ int hashCode = hash(key);
+ int index = hashIndex(hashCode, data.length);
+ HashEntry entry = data[index];
+ HashEntry previous = null;
+ while (entry != null) {
+ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
+ Object oldValue = entry.getValue();
+ removeMapping(entry, index, previous);
+ return oldValue;
+ }
+ previous = entry;
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ /**
+ * Clears the map, resetting the size to zero and nullifying references
+ * to avoid garbage collection issues.
+ */
+ public void clear() {
+ modCount++;
+ HashEntry[] data = this.data;
+ for (int i = data.length - 1; i >= 0; i--) {
+ data[i] = null;
+ }
+ size = 0;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts input keys to another object for storage in the map.
+ * This implementation masks nulls.
+ * Subclasses can override this to perform alternate key conversions.
+ *
+ * The reverse conversion can be changed, if required, by overriding the
+ * getKey() method in the hash entry.
+ *
+ * @param key the key convert
+ * @return the converted key
+ */
+ protected Object convertKey(Object key) {
+ return (key == null ? NULL : key);
+ }
+
+ /**
+ * Gets the hash code for the key specified.
+ * This implementation uses the additional hashing routine from JDK1.4.
+ * Subclasses can override this to return alternate hash codes.
+ *
+ * @param key the key to get a hash code for
+ * @return the hash code
+ */
+ protected int hash(Object key) {
+ // same as JDK 1.4
+ int h = key.hashCode();
+ h += ~(h << 9);
+ h ^= (h >>> 14);
+ h += (h << 4);
+ h ^= (h >>> 10);
+ return h;
+ }
+
+ /**
+ * Compares two keys, in internal converted form, to see if they are equal.
+ * This implementation uses the equals method and assumes neither key is null.
+ * Subclasses can override this to match differently.
+ *
+ * @param key1 the first key to compare passed in from outside
+ * @param key2 the second key extracted from the entry via
+ * This method exists for subclasses that may need to perform a multi-step
+ * process accessing the entry. The public methods in this class don't use this
+ * method to gain a small performance boost.
+ *
+ * @param key the key
+ * @return the entry, null if no match
+ */
+ protected HashEntry getEntry(Object key) {
+ key = convertKey(key);
+ int hashCode = hash(key);
+ HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
+ while (entry != null) {
+ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
+ return entry;
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Updates an existing key-value mapping to change the value.
+ *
+ * This implementation calls
+ * This implementation sets all the data fields on the entry.
+ * Subclasses could populate additional entry fields.
+ *
+ * @param entry the entry to update, not null
+ * @param hashIndex the index in the data array
+ * @param hashCode the hash code of the key to add
+ * @param key the key to add
+ * @param value the value to add
+ */
+ protected void reuseEntry(HashEntry entry, int hashIndex, int hashCode, Object key, Object value) {
+ entry.next = data[hashIndex];
+ entry.hashCode = hashCode;
+ entry.key = key;
+ entry.value = value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Adds a new key-value mapping into this map.
+ *
+ * This implementation calls
+ * This implementation creates a new HashEntry instance.
+ * Subclasses can override this to return a different storage class,
+ * or implement caching.
+ *
+ * @param next the next entry in sequence
+ * @param hashCode the hash code to use
+ * @param key the key to store
+ * @param value the value to store
+ * @return the newly created entry
+ */
+ protected HashEntry createEntry(HashEntry next, int hashCode, Object key, Object value) {
+ return new HashEntry(next, hashCode, key, value);
+ }
+
+ /**
+ * Adds an entry into this map.
+ *
+ * This implementation adds the entry to the data storage table.
+ * Subclasses could override to handle changes to the map.
+ *
+ * @param entry the entry to add
+ * @param hashIndex the index into the data array to store at
+ */
+ protected void addEntry(HashEntry entry, int hashIndex) {
+ data[hashIndex] = entry;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Removes a mapping from the map.
+ *
+ * This implementation calls
+ * This implementation removes the entry from the data storage table.
+ * The size is not updated.
+ * Subclasses could override to handle changes to the map.
+ *
+ * @param entry the entry to remove
+ * @param hashIndex the index into the data structure
+ * @param previous the previous entry in the chain
+ */
+ protected void removeEntry(HashEntry entry, int hashIndex, HashEntry previous) {
+ if (previous == null) {
+ data[hashIndex] = entry.next;
+ } else {
+ previous.next = entry.next;
+ }
+ }
+
+ /**
+ * Kills an entry ready for the garbage collector.
+ *
+ * This implementation prepares the HashEntry for garbage collection.
+ * Subclasses can override this to implement caching (override clear as well).
+ *
+ * @param entry the entry to destroy
+ */
+ protected void destroyEntry(HashEntry entry) {
+ entry.next = null;
+ entry.key = null;
+ entry.value = null;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks the capacity of the map and enlarges it if necessary.
+ *
+ * This implementation uses the threshold to check if the map needs enlarging
+ */
+ protected void checkCapacity() {
+ if (size >= threshold) {
+ int newCapacity = data.length * 2;
+ if (newCapacity <= MAXIMUM_CAPACITY) {
+ ensureCapacity(newCapacity);
+ }
+ }
+ }
+
+ /**
+ * Changes the size of the data structure to the capacity proposed.
+ *
+ * @param newCapacity the new capacity of the array (a power of two, less or equal to max)
+ */
+ protected void ensureCapacity(int newCapacity) {
+ int oldCapacity = data.length;
+ if (newCapacity <= oldCapacity) {
+ return;
+ }
+ if (size == 0) {
+ threshold = calculateThreshold(newCapacity, loadFactor);
+ data = new HashEntry[newCapacity];
+ } else {
+ HashEntry oldEntries[] = data;
+ HashEntry newEntries[] = new HashEntry[newCapacity];
+
+ modCount++;
+ for (int i = oldCapacity - 1; i >= 0; i--) {
+ HashEntry entry = oldEntries[i];
+ if (entry != null) {
+ oldEntries[i] = null; // gc
+ do {
+ HashEntry next = entry.next;
+ int index = hashIndex(entry.hashCode, newCapacity);
+ entry.next = newEntries[index];
+ newEntries[index] = entry;
+ entry = next;
+ } while (entry != null);
+ }
+ }
+ threshold = calculateThreshold(newCapacity, loadFactor);
+ data = newEntries;
+ }
+ }
+
+ /**
+ * Calculates the new capacity of the map.
+ * This implementation normalizes the capacity to a power of two.
+ *
+ * @param proposedCapacity the proposed capacity
+ * @return the normalized new capacity
+ */
+ protected int calculateNewCapacity(int proposedCapacity) {
+ int newCapacity = 1;
+ if (proposedCapacity > MAXIMUM_CAPACITY) {
+ newCapacity = MAXIMUM_CAPACITY;
+ } else {
+ while (newCapacity < proposedCapacity) {
+ newCapacity <<= 1; // multiply by two
+ }
+ if (newCapacity > MAXIMUM_CAPACITY) {
+ newCapacity = MAXIMUM_CAPACITY;
+ }
+ }
+ return newCapacity;
+ }
+
+ /**
+ * Calculates the new threshold of the map, where it will be resized.
+ * This implementation uses the load factor.
+ *
+ * @param newCapacity the new capacity
+ * @param factor the load factor
+ * @return the new resize threshold
+ */
+ protected int calculateThreshold(int newCapacity, float factor) {
+ return (int) (newCapacity * factor);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the
+ * A MapIterator returns the keys in the map. It also provides convenient
+ * methods to get the key and value, and set the value.
+ * It avoids the need to create an entrySet/keySet/values object.
+ * It also avoids creating the Map.Entry object.
+ *
+ * @return the map iterator
+ */
+ public MapIterator mapIterator() {
+ if (size == 0) {
+ return EmptyMapIterator.INSTANCE;
+ }
+ return new HashMapIterator(this);
+ }
+
+ /**
+ * MapIterator implementation.
+ */
+ protected static class HashMapIterator extends HashIterator implements MapIterator {
+
+ protected HashMapIterator(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return super.nextEntry().getKey();
+ }
+
+ public Object getKey() {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
+ }
+ return current.getKey();
+ }
+
+ public Object getValue() {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
+ }
+ return current.getValue();
+ }
+
+ public Object setValue(Object value) {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
+ }
+ return current.setValue(value);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the entrySet view of the map.
+ * Changes made to the view affect this map.
+ * To simply iterate through the entries, use {@link #mapIterator()}.
+ *
+ * @return the entrySet view
+ */
+ public Set entrySet() {
+ if (entrySet == null) {
+ entrySet = new EntrySet(this);
+ }
+ return entrySet;
+ }
+
+ /**
+ * Creates an entry set iterator.
+ * Subclasses can override this to return iterators with different properties.
+ *
+ * @return the entrySet iterator
+ */
+ protected Iterator createEntrySetIterator() {
+ if (size() == 0) {
+ return EmptyIterator.INSTANCE;
+ }
+ return new EntrySetIterator(this);
+ }
+
+ /**
+ * EntrySet implementation.
+ */
+ protected static class EntrySet extends AbstractSet {
+ /** The parent map */
+ protected final AbstractHashedMap parent;
+
+ protected EntrySet(AbstractHashedMap parent) {
+ super();
+ this.parent = parent;
+ }
+
+ public int size() {
+ return parent.size();
+ }
+
+ public void clear() {
+ parent.clear();
+ }
+
+ public boolean contains(Object entry) {
+ if (entry instanceof Map.Entry) {
+ Map.Entry e = (Map.Entry) entry;
+ Entry match = parent.getEntry(e.getKey());
+ return (match != null && match.equals(e));
+ }
+ return false;
+ }
+
+ public boolean remove(Object obj) {
+ if (obj instanceof Map.Entry == false) {
+ return false;
+ }
+ if (contains(obj) == false) {
+ return false;
+ }
+ Map.Entry entry = (Map.Entry) obj;
+ Object key = entry.getKey();
+ parent.remove(key);
+ return true;
+ }
+
+ public Iterator iterator() {
+ return parent.createEntrySetIterator();
+ }
+ }
+
+ /**
+ * EntrySet iterator.
+ */
+ protected static class EntrySetIterator extends HashIterator {
+
+ protected EntrySetIterator(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return super.nextEntry();
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the keySet view of the map.
+ * Changes made to the view affect this map.
+ * To simply iterate through the keys, use {@link #mapIterator()}.
+ *
+ * @return the keySet view
+ */
+ public Set keySet() {
+ if (keySet == null) {
+ keySet = new KeySet(this);
+ }
+ return keySet;
+ }
+
+ /**
+ * Creates a key set iterator.
+ * Subclasses can override this to return iterators with different properties.
+ *
+ * @return the keySet iterator
+ */
+ protected Iterator createKeySetIterator() {
+ if (size() == 0) {
+ return EmptyIterator.INSTANCE;
+ }
+ return new KeySetIterator(this);
+ }
+
+ /**
+ * KeySet implementation.
+ */
+ protected static class KeySet extends AbstractSet {
+ /** The parent map */
+ protected final AbstractHashedMap parent;
+
+ protected KeySet(AbstractHashedMap parent) {
+ super();
+ this.parent = parent;
+ }
+
+ public int size() {
+ return parent.size();
+ }
+
+ public void clear() {
+ parent.clear();
+ }
+
+ public boolean contains(Object key) {
+ return parent.containsKey(key);
+ }
+
+ public boolean remove(Object key) {
+ boolean result = parent.containsKey(key);
+ parent.remove(key);
+ return result;
+ }
+
+ public Iterator iterator() {
+ return parent.createKeySetIterator();
+ }
+ }
+
+ /**
+ * KeySet iterator.
+ */
+ protected static class KeySetIterator extends EntrySetIterator {
+
+ protected KeySetIterator(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return super.nextEntry().getKey();
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the values view of the map.
+ * Changes made to the view affect this map.
+ * To simply iterate through the values, use {@link #mapIterator()}.
+ *
+ * @return the values view
+ */
+ public Collection values() {
+ if (values == null) {
+ values = new Values(this);
+ }
+ return values;
+ }
+
+ /**
+ * Creates a values iterator.
+ * Subclasses can override this to return iterators with different properties.
+ *
+ * @return the values iterator
+ */
+ protected Iterator createValuesIterator() {
+ if (size() == 0) {
+ return EmptyIterator.INSTANCE;
+ }
+ return new ValuesIterator(this);
+ }
+
+ /**
+ * Values implementation.
+ */
+ protected static class Values extends AbstractCollection {
+ /** The parent map */
+ protected final AbstractHashedMap parent;
+
+ protected Values(AbstractHashedMap parent) {
+ super();
+ this.parent = parent;
+ }
+
+ public int size() {
+ return parent.size();
+ }
+
+ public void clear() {
+ parent.clear();
+ }
+
+ public boolean contains(Object value) {
+ return parent.containsValue(value);
+ }
+
+ public Iterator iterator() {
+ return parent.createValuesIterator();
+ }
+ }
+
+ /**
+ * Values iterator.
+ */
+ protected static class ValuesIterator extends HashIterator {
+
+ protected ValuesIterator(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return super.nextEntry().getValue();
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * HashEntry used to store the data.
+ *
+ * If you subclass
+ * Serialization is not one of the JDK's nicest topics. Normal serialization will
+ * initialise the superclass before the subclass. Sometimes however, this isn't
+ * what you want, as in this case the
+ * The solution adopted here is to serialize the state data of this class in
+ * this protected method. This method must be called by the
+ *
+ * Subclasses may override if they have a specific field that must be present
+ * on read before this implementation will work. Generally, the read determines
+ * what must be serialized here, if anything.
+ *
+ * @param out the output stream
+ */
+ protected void doWriteObject(ObjectOutputStream out) throws IOException {
+ out.writeFloat(loadFactor);
+ out.writeInt(data.length);
+ out.writeInt(size);
+ for (MapIterator it = mapIterator(); it.hasNext();) {
+ out.writeObject(it.next());
+ out.writeObject(it.getValue());
+ }
+ }
+
+ /**
+ * Reads the map data from the stream. This method must be overridden if a
+ * subclass must be setup before
+ * Serialization is not one of the JDK's nicest topics. Normal serialization will
+ * initialise the superclass before the subclass. Sometimes however, this isn't
+ * what you want, as in this case the
+ * The solution adopted here is to deserialize the state data of this class in
+ * this protected method. This method must be called by the
+ *
+ * Subclasses may override if the subclass has a specific field that must be present
+ * before
+ * To implement
+ * This class implements all the features necessary for a subclass reference
+ * hash-based map. Key-value entries are stored in instances of the
+ *
+ * Overridable methods are provided to change the default hashing behaviour, and
+ * to change how entries are added to and removed from the map. Hopefully, all you
+ * need for unusual subclasses is here.
+ *
+ * When you construct an
+ * Different types of references can be specified for keys and values.
+ * The keys can be configured to be weak but the values hard,
+ * in which case this class will behave like a
+ *
+ *
+ * This {@link Map} implementation does not allow null elements.
+ * Attempting to add a null key or value to the map will raise a
+ *
+ * All the available iterators can be reset back to the start by casting to
+ *
+ * This implementation is not synchronized.
+ * You can use {@link java.util.Collections#synchronizedMap} to
+ * provide synchronized access to a
+ * This implementation calls {@link #purge()} to maintain a consistent state.
+ */
+ protected void purgeBeforeRead() {
+ purge();
+ }
+
+ /**
+ * Purges stale mappings from this map before write operations.
+ *
+ * This implementation calls {@link #purge()} to maintain a consistent state.
+ */
+ protected void purgeBeforeWrite() {
+ purge();
+ }
+
+ /**
+ * Purges stale mappings from this map.
+ *
+ * Note that this method is not synchronized! Special
+ * care must be taken if, for instance, you want stale
+ * mappings to be removed on a periodic basis by some
+ * background thread.
+ */
+ protected void purge() {
+ Reference ref = queue.poll();
+ while (ref != null) {
+ purge(ref);
+ ref = queue.poll();
+ }
+ }
+
+ /**
+ * Purges the specified reference.
+ *
+ * @param ref the reference to purge
+ */
+ protected void purge(Reference ref) {
+ // The hashCode of the reference is the hashCode of the
+ // mapping key, even if the reference refers to the
+ // mapping value...
+ int hash = ref.hashCode();
+ int index = hashIndex(hash, data.length);
+ HashEntry previous = null;
+ HashEntry entry = data[index];
+ while (entry != null) {
+ if (((ReferenceEntry) entry).purge(ref)) {
+ if (previous == null) {
+ data[index] = entry.next;
+ } else {
+ previous.next = entry.next;
+ }
+ this.size--;
+ return;
+ }
+ previous = entry;
+ entry = entry.next;
+ }
+
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the entry mapped to the key specified.
+ *
+ * @param key the key
+ * @return the entry, null if no match
+ */
+ protected HashEntry getEntry(Object key) {
+ if (key == null) {
+ return null;
+ } else {
+ return super.getEntry(key);
+ }
+ }
+
+ /**
+ * Gets the hash code for a MapEntry.
+ * Subclasses can override this, for example to use the identityHashCode.
+ *
+ * @param key the key to get a hash code for, may be null
+ * @param value the value to get a hash code for, may be null
+ * @return the hash code, as per the MapEntry specification
+ */
+ protected int hashEntry(Object key, Object value) {
+ return (key == null ? 0 : key.hashCode()) ^
+ (value == null ? 0 : value.hashCode());
+ }
+
+ /**
+ * Compares two keys, in internal converted form, to see if they are equal.
+ *
+ * This implementation converts the key from the entry to a real reference
+ * before comparison.
+ *
+ * @param key1 the first key to compare passed in from outside
+ * @param key2 the second key extracted from the entry via
+ * If getKey() or getValue() returns null, it means
+ * the mapping is stale and should be removed.
+ *
+ * @since Commons Collections 3.1
+ */
+ protected static class ReferenceEntry extends HashEntry {
+ /** The parent map */
+ protected final AbstractReferenceMap parent;
+
+ /**
+ * Creates a new entry object for the ReferenceMap.
+ *
+ * @param parent the parent map
+ * @param next the next entry in the hash bucket
+ * @param hashCode the hash code of the key
+ * @param key the key
+ * @param value the value
+ */
+ public ReferenceEntry(AbstractReferenceMap parent, HashEntry next, int hashCode, Object key, Object value) {
+ super(next, hashCode, null, null);
+ this.parent = parent;
+ this.key = toReference(parent.keyType, key, hashCode);
+ this.value = toReference(parent.valueType, value, hashCode); // the key hashCode is passed in deliberately
+ }
+
+ /**
+ * Gets the key from the entry.
+ * This method dereferences weak and soft keys and thus may return null.
+ *
+ * @return the key, which may be null if it was garbage collected
+ */
+ public Object getKey() {
+ return (parent.keyType > HARD) ? ((Reference) key).get() : key;
+ }
+
+ /**
+ * Gets the value from the entry.
+ * This method dereferences weak and soft value and thus may return null.
+ *
+ * @return the value, which may be null if it was garbage collected
+ */
+ public Object getValue() {
+ return (parent.valueType > HARD) ? ((Reference) value).get() : value;
+ }
+
+ /**
+ * Sets the value of the entry.
+ *
+ * @param obj the object to store
+ * @return the previous value
+ */
+ public Object setValue(Object obj) {
+ Object old = getValue();
+ if (parent.valueType > HARD) {
+ ((Reference)value).clear();
+ }
+ value = toReference(parent.valueType, obj, hashCode);
+ return old;
+ }
+
+ /**
+ * Compares this map entry to another.
+ *
+ * This implementation uses
+ * This implementation uses
+ * Serialization is not one of the JDK's nicest topics. Normal serialization will
+ * initialise the superclass before the subclass. Sometimes however, this isn't
+ * what you want, as in this case the
+ * The solution adopted here is to serialize the state data of this class in
+ * this protected method. This method must be called by the
+ *
+ * Subclasses may override if they have a specific field that must be present
+ * on read before this implementation will work. Generally, the read determines
+ * what must be serialized here, if anything.
+ *
+ * @param out the output stream
+ */
+ protected void doWriteObject(ObjectOutputStream out) throws IOException {
+ out.writeInt(keyType);
+ out.writeInt(valueType);
+ out.writeBoolean(purgeValues);
+ out.writeFloat(loadFactor);
+ out.writeInt(data.length);
+ for (MapIterator it = mapIterator(); it.hasNext();) {
+ out.writeObject(it.next());
+ out.writeObject(it.getValue());
+ }
+ out.writeObject(null); // null terminate map
+ // do not call super.doWriteObject() as code there doesn't work for reference map
+ }
+
+ /**
+ * Replaces the superclassm method to read the state of this class.
+ *
+ * Serialization is not one of the JDK's nicest topics. Normal serialization will
+ * initialise the superclass before the subclass. Sometimes however, this isn't
+ * what you want, as in this case the
+ * The solution adopted here is to deserialize the state data of this class in
+ * this protected method. This method must be called by the
+ *
+ * Subclasses may override if the subclass has a specific field that must be present
+ * before
+ * When you construct a
+ * Different types of references can be specified for keys and values.
+ * The keys can be configured to be weak but the values hard,
+ * in which case this class will behave like a
+ *
+ *
+ * This map is similar to
+ * {@link org.apache.commons.collections.map.ReferenceIdentityMap ReferenceIdentityMap}.
+ * It differs in that keys and values in this class are compared using
+ * This {@link java.util.Map Map} implementation does not allow null elements.
+ * Attempting to add a null key or value to the map will raise a
+ * This implementation is not synchronized.
+ * You can use {@link java.util.Collections#synchronizedMap} to
+ * provide synchronized access to a
+ * All the available iterators can be reset back to the start by casting to
+ *
+ * Note that ReferenceMap is not synchronized and is not thread-safe.
+ * If you wish to use this map from multiple threads concurrently, you must use
+ * appropriate synchronization. The simplest approach is to wrap this map
+ * using {@link java.util.Collections#synchronizedMap}. This class may throw
+ * exceptions when accessed by concurrent threads without synchronization.
+ *
+ * NOTE: As from Commons Collections 3.1 this map extends
+ * If you use this interface your class should also implement the getInstance
+ * pattern which takes a tag object and the tagging mode used.
+ */
+public interface ASN1Choice
+{
+ // marker interface
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Encodable.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Encodable.java
new file mode 100644
index 00000000..77573a28
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Encodable.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Base class for objects which can be written directly to ASN.1 output streams.
+ */
+public abstract class ASN1Encodable
+ implements DEREncodable
+{
+ public static final String DER = "DER";
+ public static final String BER = "BER";
+
+ /**
+ * Return the default BER or DER encoding for this object.
+ *
+ * @return BER/DER byte encoded object.
+ * @throws IOException on encoding error.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Return either the default for "BER" or a DER encoding if "DER" is specified.
+ *
+ * @param encoding name of encoding to use.
+ * @return byte encoded object.
+ * @throws IOException on encoding error.
+ */
+ public byte[] getEncoded(
+ String encoding)
+ throws IOException
+ {
+ if (encoding.equals(DER))
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ return this.getEncoded();
+ }
+
+ /**
+ * Return the DER encoding of the object, null if the DER encoding can not be made.
+ *
+ * @return a DER byte array, null otherwise.
+ */
+ public byte[] getDEREncoded()
+ {
+ try
+ {
+ return this.getEncoded(DER);
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ public int hashCode()
+ {
+ return this.toASN1Object().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof DEREncodable))
+ {
+ return false;
+ }
+
+ DEREncodable other = (DEREncodable)o;
+
+ return this.toASN1Object().equals(other.getDERObject());
+ }
+
+ public DERObject getDERObject()
+ {
+ return this.toASN1Object();
+ }
+
+ public abstract DERObject toASN1Object();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1EncodableVector.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1EncodableVector.java
new file mode 100644
index 00000000..7e9bf529
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1EncodableVector.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.asn1;
+
+/**
+ * the parent class for this will eventually disappear. Use this one!
+ */
+public class ASN1EncodableVector
+ extends DEREncodableVector
+{
+ // migrating from DEREncodeableVector
+ @SuppressWarnings("deprecation")
+ public ASN1EncodableVector()
+ {
+
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Generator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Generator.java
new file mode 100644
index 00000000..50cb7054
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Generator.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.asn1;
+
+import java.io.OutputStream;
+
+public abstract class ASN1Generator
+{
+ protected OutputStream _out;
+
+ public ASN1Generator(OutputStream out)
+ {
+ _out = out;
+ }
+
+ public abstract OutputStream getRawOutputStream();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1InputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1InputStream.java
new file mode 100644
index 00000000..45c34a3e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1InputStream.java
@@ -0,0 +1,387 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.util.io.Streams;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+ extends FilterInputStream
+ implements DERTags
+{
+ private final int limit;
+ private final boolean lazyEvaluate;
+
+ public ASN1InputStream(
+ InputStream is)
+ {
+ this(is, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public ASN1InputStream(
+ byte[] input)
+ {
+ this(new ByteArrayInputStream(input), input.length);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ byte[] input,
+ boolean lazyEvaluate)
+ {
+ this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit)
+ {
+ this(input, limit, false);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit,
+ boolean lazyEvaluate)
+ {
+ super(input);
+ this.limit = limit;
+ this.lazyEvaluate = lazyEvaluate;
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ return readLength(this, limit);
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ if (Streams.readFully(this, bytes) != bytes.length)
+ {
+ throw new EOFException("EOF encountered in middle of object");
+ }
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ */
+ protected DERObject buildObject(
+ int tag,
+ int tagNo,
+ int length)
+ throws IOException
+ {
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(tag, tagNo, defIn).getDERObject();
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BERConstructedOctetString(buildDEREncodableVector(defIn).v);
+ case SEQUENCE:
+ if (lazyEvaluate)
+ {
+ assert(false);
+ //return new LazyDERSequence(defIn.toByteArray());
+ }
+ else
+ {
+ return DERFactory.createSequence(buildDEREncodableVector(defIn));
+ }
+ case SET:
+ return DERFactory.createSet(buildDEREncodableVector(defIn), false);
+ case EXTERNAL:
+ return new DERExternal(buildDEREncodableVector(defIn));
+ default:
+ return new DERUnknownTag(true, tagNo, defIn.toByteArray());
+ }
+ }
+
+ return createPrimitiveDERObject(tagNo, defIn.toByteArray());
+ }
+
+ ASN1EncodableVector buildEncodableVector()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ DERObject o;
+
+ while ((o = readObject()) != null)
+ {
+ v.add(o);
+ }
+
+ return v;
+ }
+
+ ASN1EncodableVector buildDEREncodableVector(
+ DefiniteLengthInputStream dIn) throws IOException
+ {
+ return new ASN1InputStream(dIn).buildEncodableVector();
+ }
+
+ public DERObject readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ {
+ throw new IOException("unexpected end-of-contents marker");
+ }
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = readTagNumber(this, tag);
+
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ return new BERApplicationSpecificParser(tagNo, sp).getDERObject();
+ }
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(tag, tagNo, indIn).getDERObject();
+ }
+
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ return new BEROctetStringParser(sp).getDERObject();
+ case SEQUENCE:
+ return new BERSequenceParser(sp).getDERObject();
+ case SET:
+ return new BERSetParser(sp).getDERObject();
+ case EXTERNAL:
+ return new DERExternalParser(sp).getDERObject();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ return buildObject(tag, tagNo, length);
+ }
+ }
+
+ static int readTagNumber(InputStream s, int tag)
+ throws IOException
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.read();
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new IOException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.read();
+ }
+
+ if (b < 0)
+ {
+ throw new EOFException("EOF found inside tag value.");
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ static int readLength(InputStream s, int limit)
+ throws IOException
+ {
+ int length = s.read();
+ if (length < 0)
+ {
+ throw new EOFException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes: " + size);
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.read();
+
+ if (next < 0)
+ {
+ throw new EOFException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ {
+ throw new IOException("corrupted stream - out of bounds length found");
+ }
+ }
+
+ return length;
+ }
+
+ static DERObject createPrimitiveDERObject(
+ int tagNo,
+ byte[] bytes)
+ {
+ switch (tagNo)
+ {
+ case BIT_STRING:
+ {
+ int padBits = bytes[0];
+ byte[] data = new byte[bytes.length - 1];
+ System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+ return new DERBitString(data, padBits);
+ }
+ case BMP_STRING:
+ return new DERBMPString(bytes);
+ case BOOLEAN:
+ return new DERBoolean(bytes);
+ case ENUMERATED:
+ return new DEREnumerated(bytes);
+ case GENERALIZED_TIME:
+ return new DERGeneralizedTime(bytes);
+ case GENERAL_STRING:
+ return new DERGeneralString(bytes);
+ case IA5_STRING:
+ return new DERIA5String(bytes);
+ case INTEGER:
+ return new DERInteger(bytes);
+ case NULL:
+ return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
+ case NUMERIC_STRING:
+ return new DERNumericString(bytes);
+ case OBJECT_IDENTIFIER:
+ return new DERObjectIdentifier(bytes);
+ case OCTET_STRING:
+ return new DEROctetString(bytes);
+ case PRINTABLE_STRING:
+ return new DERPrintableString(bytes);
+ case T61_STRING:
+ return new DERT61String(bytes);
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(bytes);
+ case UTC_TIME:
+ return new DERUTCTime(bytes);
+ case UTF8_STRING:
+ return new DERUTF8String(bytes);
+ case VISIBLE_STRING:
+ return new DERVisibleString(bytes);
+ default:
+ return new DERUnknownTag(false, tagNo, bytes);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Null.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Null.java
new file mode 100644
index 00000000..b9b849d2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Null.java
@@ -0,0 +1,38 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object.
+ */
+public abstract class ASN1Null
+ extends ASN1Object
+{
+ public ASN1Null()
+ {
+ }
+
+ public int hashCode()
+ {
+ return -1;
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof ASN1Null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "NULL";
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Object.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Object.java
new file mode 100644
index 00000000..7a0b1137
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Object.java
@@ -0,0 +1,38 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public abstract class ASN1Object
+ extends DERObject
+{
+ /**
+ * Create a base ASN.1 object from a byte stream.
+ *
+ * @param data the byte stream to parse.
+ * @return the base ASN.1 object represented by the byte stream.
+ * @exception IOException if there is a problem parsing the data.
+ */
+ public static ASN1Object fromByteArray(byte[] data)
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(data);
+
+ return (ASN1Object)aIn.readObject();
+ }
+
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ return (o instanceof DEREncodable) && asn1Equals(((DEREncodable)o).getDERObject());
+ }
+
+ public abstract int hashCode();
+
+ abstract void encode(DEROutputStream out) throws IOException;
+
+ abstract boolean asn1Equals(DERObject o);
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ObjectParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ObjectParser.java
new file mode 100644
index 00000000..ff09a454
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ObjectParser.java
@@ -0,0 +1,19 @@
+package org.bouncycastle.asn1;
+
+import java.io.InputStream;
+
+/**
+ * @deprecated will be removed
+ */
+public class ASN1ObjectParser
+{
+ ASN1StreamParser _aIn;
+
+ protected ASN1ObjectParser(
+ int baseTag,
+ int tagNumber,
+ InputStream contentStream)
+ {
+ _aIn = new ASN1StreamParser(contentStream);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetString.java
new file mode 100644
index 00000000..d235458e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetString.java
@@ -0,0 +1,136 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.encoders.Hex;
+import org.bouncycastle.util.Arrays;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class ASN1OctetString
+ extends ASN1Object
+ implements ASN1OctetStringParser
+{
+ byte[] string;
+
+ /**
+ * return an Octet 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.
+ */
+ public static ASN1OctetString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * return an Octet String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ @SuppressWarnings("unchecked")
+ public static ASN1OctetString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1OctetString)
+ {
+ return (ASN1OctetString)obj;
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ Vector v = new Vector();
+ Enumeration e = ((ASN1Sequence)obj).getObjects();
+
+ while (e.hasMoreElements())
+ {
+ v.addElement(e.nextElement());
+ }
+
+ return new BERConstructedOctetString(v);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public ASN1OctetString(
+ byte[] string)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ this.string = string;
+ }
+
+ public ASN1OctetString(
+ DEREncodable obj)
+ {
+ try
+ {
+ this.string = obj.getDERObject().getEncoded(ASN1Encodable.DER);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Error processing object : " + e.toString());
+ }
+ }
+
+ public InputStream getOctetStream()
+ {
+ return new ByteArrayInputStream(string);
+ }
+
+ public ASN1OctetStringParser parser()
+ {
+ return this;
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(this.getOctets());
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof ASN1OctetString))
+ {
+ return false;
+ }
+
+ ASN1OctetString other = (ASN1OctetString)o;
+
+ return Arrays.areEqual(string, other.string);
+ }
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "#"+new String(Hex.encode(string));
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetStringParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetStringParser.java
new file mode 100644
index 00000000..641020c1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OctetStringParser.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.asn1;
+
+import java.io.InputStream;
+
+public interface ASN1OctetStringParser
+ extends DEREncodable
+{
+ public InputStream getOctetStream();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OutputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OutputStream.java
new file mode 100644
index 00000000..5897d09f
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1OutputStream.java
@@ -0,0 +1,36 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class ASN1OutputStream
+ extends DEROutputStream
+{
+ public ASN1OutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ Object obj)
+ throws IOException
+ {
+ if (obj == null)
+ {
+ writeNull();
+ }
+ else if (obj instanceof DERObject)
+ {
+ ((DERObject)obj).encode(this);
+ }
+ else if (obj instanceof DEREncodable)
+ {
+ ((DEREncodable)obj).getDERObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("object not ASN1Encodable");
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ParsingException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ParsingException.java
new file mode 100644
index 00000000..2f4dc818
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ParsingException.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.asn1;
+
+@SuppressWarnings("serial")
+public class ASN1ParsingException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ ASN1ParsingException(String message)
+ {
+ super(message);
+ }
+
+ ASN1ParsingException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Sequence.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Sequence.java
new file mode 100644
index 00000000..da80adec
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Sequence.java
@@ -0,0 +1,218 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+@SuppressWarnings("unchecked")
+public abstract class ASN1Sequence
+ extends ASN1Object
+{
+ private Vector seq = new Vector();
+
+ /**
+ * return an ASN1Sequence from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Sequence getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj;
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 sequence from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * sequence - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sequences you really should
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @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 ASN1Sequence getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return (ASN1Sequence)obj.getObject();
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // when it should be implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.isExplicit())
+ {
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSequence(obj.getObject());
+ }
+ else
+ {
+ return new DERSequence(obj.getObject());
+ }
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj.getObject();
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ public Enumeration getObjects()
+ {
+ return seq.elements();
+ }
+
+ public ASN1SequenceParser parser()
+ {
+ final ASN1Sequence outer = this;
+
+ return new ASN1SequenceParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public DEREncodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ DEREncodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public DERObject getDERObject()
+ {
+ return outer;
+ }
+ };
+ }
+
+ /**
+ * 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.
+ */
+ public DEREncodable getObjectAt(
+ int index)
+ {
+ return (DEREncodable)seq.elementAt(index);
+ }
+
+ /**
+ * return the number of objects in this sequence.
+ *
+ * @return the number of objects in this sequence.
+ */
+ public int size()
+ {
+ return seq.size();
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+ hashCode *= 17;
+ if (o != null)
+ {
+ hashCode ^= o.hashCode();
+ }
+ }
+
+ return hashCode;
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Sequence other = (ASN1Sequence)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
+ DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
+
+ if (o1 == o2 || (o1 != null && o1.equals(o2)))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ protected void addObject(
+ DEREncodable obj)
+ {
+ seq.addElement(obj);
+ }
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return seq.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SequenceParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SequenceParser.java
new file mode 100644
index 00000000..ceda6bdd
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SequenceParser.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SequenceParser
+ extends DEREncodable
+{
+ DEREncodable readObject()
+ throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Set.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Set.java
new file mode 100644
index 00000000..2eaafe0e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Set.java
@@ -0,0 +1,344 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+@SuppressWarnings("unchecked")
+abstract public class ASN1Set
+ extends ASN1Object
+{
+ protected Vector set = new Vector();
+
+ /**
+ * return an ASN1Set from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Set getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Set)
+ {
+ return (ASN1Set)obj;
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 set from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * set - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sets you really should
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @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 ASN1Set getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return (ASN1Set)obj.getObject();
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // and it's really implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.isExplicit())
+ {
+ ASN1Set set = new DERSet(obj.getObject());
+
+ return set;
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Set)
+ {
+ return (ASN1Set)obj.getObject();
+ }
+
+ //
+ // in this case the parser returns a sequence, convert it
+ // into a set.
+ //
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ ASN1Sequence s = (ASN1Sequence)obj.getObject();
+ Enumeration e = s.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ v.add((DEREncodable)e.nextElement());
+ }
+
+ return new DERSet(v, false);
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ public ASN1Set()
+ {
+ }
+
+ public Enumeration getObjects()
+ {
+ return set.elements();
+ }
+
+ /**
+ * return the object at the set position indicated by index.
+ *
+ * @param index the set number (starting at zero) of the object
+ * @return the object at the set position indicated by index.
+ */
+ public DEREncodable getObjectAt(
+ int index)
+ {
+ return (DEREncodable)set.elementAt(index);
+ }
+
+ /**
+ * return the number of objects in this set.
+ *
+ * @return the number of objects in this set.
+ */
+ public int size()
+ {
+ return set.size();
+ }
+
+ public ASN1SetParser parser()
+ {
+ final ASN1Set outer = this;
+
+ return new ASN1SetParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public DEREncodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ DEREncodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public DERObject getDERObject()
+ {
+ return outer;
+ }
+ };
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+ hashCode *= 17;
+ if (o != null)
+ {
+ hashCode ^= o.hashCode();
+ }
+ }
+
+ return hashCode;
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof ASN1Set))
+ {
+ return false;
+ }
+
+ ASN1Set other = (ASN1Set)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
+ DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
+
+ if (o1 == o2 || (o1 != null && o1.equals(o2)))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * return true if a <= b (arrays are assumed padded with zeros).
+ */
+ private boolean lessThanOrEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a.length <= b.length)
+ {
+ for (int i = 0; i != a.length; i++)
+ {
+ int l = a[i] & 0xff;
+ int r = b[i] & 0xff;
+
+ if (r > l)
+ {
+ return true;
+ }
+ else if (l > r)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ else
+ {
+ for (int i = 0; i != b.length; i++)
+ {
+ int l = a[i] & 0xff;
+ int r = b[i] & 0xff;
+
+ if (r > l)
+ {
+ return true;
+ }
+ else if (l > r)
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private byte[] getEncoded(
+ DEREncodable obj)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(obj);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("cannot encode object added to SET");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ protected void sort()
+ {
+ if (set.size() > 1)
+ {
+ boolean swapped = true;
+ int lastSwap = set.size() - 1;
+
+ while (swapped)
+ {
+ int index = 0;
+ int swapIndex = 0;
+ byte[] a = getEncoded((DEREncodable)set.elementAt(0));
+
+ swapped = false;
+
+ while (index != lastSwap)
+ {
+ byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
+
+ if (lessThanOrEqual(a, b))
+ {
+ a = b;
+ }
+ else
+ {
+ Object o = set.elementAt(index);
+
+ set.setElementAt(set.elementAt(index + 1), index);
+ set.setElementAt(o, index + 1);
+
+ swapped = true;
+ swapIndex = index;
+ }
+
+ index++;
+ }
+
+ lastSwap = swapIndex;
+ }
+ }
+ }
+
+ protected void addObject(
+ DEREncodable obj)
+ {
+ set.addElement(obj);
+ }
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return set.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SetParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SetParser.java
new file mode 100644
index 00000000..b09a1704
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1SetParser.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SetParser
+ extends DEREncodable
+{
+ public DEREncodable readObject()
+ throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1StreamParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1StreamParser.java
new file mode 100644
index 00000000..43fcad76
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1StreamParser.java
@@ -0,0 +1,174 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1StreamParser
+{
+ private final InputStream _in;
+ private final int _limit;
+
+ private static int findLimit(InputStream in)
+ {
+ if (in instanceof DefiniteLengthInputStream)
+ {
+ return ((DefiniteLengthInputStream)in).getRemaining();
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ public ASN1StreamParser(
+ InputStream in)
+ {
+ this(in, findLimit(in));
+ }
+
+ public ASN1StreamParser(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+ }
+
+ public ASN1StreamParser(
+ byte[] encoding)
+ {
+ this(new ByteArrayInputStream(encoding), encoding.length);
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ int tag = _in.read();
+ if (tag == -1)
+ {
+ return null;
+ }
+
+ //
+ // turn of looking for "00" while we resolve the tag
+ //
+ set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ASN1InputStream.readTagNumber(_in, tag);
+
+ boolean isConstructed = (tag & DERTags.CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ASN1InputStream.readLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
+
+ if ((tag & DERTags.APPLICATION) != 0)
+ {
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ return new BERApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & DERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(tag, tagNo, indIn);
+ }
+
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case DERTags.OCTET_STRING:
+ return new BEROctetStringParser(sp);
+ case DERTags.SEQUENCE:
+ return new BERSequenceParser(sp);
+ case DERTags.SET:
+ return new BERSetParser(sp);
+ case DERTags.EXTERNAL:{
+ return new DERExternalParser(sp);
+ }
+ default:
+ throw new IOException("unknown BER object encountered: 0x" + Integer.toHexString(tagNo));
+ }
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & DERTags.APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & DERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(tag, tagNo, defIn);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case DERTags.OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BEROctetStringParser(new ASN1StreamParser(defIn));
+ case DERTags.SEQUENCE:
+ return new DERSequenceParser(new ASN1StreamParser(defIn));
+ case DERTags.SET:
+ return new DERSetParser(new ASN1StreamParser(defIn));
+ case DERTags.EXTERNAL:
+ return new DERExternalParser(new ASN1StreamParser(defIn));
+ default:
+ // TODO Add DERUnknownTagParser class?
+ return new DERUnknownTag(true, tagNo, defIn.toByteArray());
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case DERTags.OCTET_STRING:
+ return new DEROctetStringParser(defIn);
+ }
+
+ return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn.toByteArray());
+ }
+ }
+
+ private void set00Check(boolean enabled)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
+ }
+ }
+
+ ASN1EncodableVector readVector() throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ DEREncodable obj;
+ while ((obj = readObject()) != null)
+ {
+ v.add(obj.getDERObject());
+ }
+
+ return v;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObject.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObject.java
new file mode 100644
index 00000000..1e5d4e88
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObject.java
@@ -0,0 +1,210 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public abstract class ASN1TaggedObject
+ extends ASN1Object
+ implements ASN1TaggedObjectParser
+{
+ int tagNo;
+ boolean empty = false;
+ boolean explicit = true;
+ DEREncodable obj = null;
+
+ static public ASN1TaggedObject getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ return (ASN1TaggedObject)obj.getObject();
+ }
+
+ throw new IllegalArgumentException("implicitly tagged tagged object");
+ }
+
+ static public ASN1TaggedObject getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1TaggedObject)
+ {
+ return (ASN1TaggedObject)obj;
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Create a tagged object in the explicit style.
+ *
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public ASN1TaggedObject(
+ int tagNo,
+ DEREncodable obj)
+ {
+ this.explicit = true;
+ this.tagNo = tagNo;
+ this.obj = obj;
+ }
+
+ /**
+ * Create a tagged object with the style given by the value of explicit.
+ *
+ * If the object implements ASN1Choice the tag style will always be changed
+ * to explicit in accordance with the ASN.1 encoding rules.
+ *
+ * Note: if the object has been read from an input stream, the only
+ * time you can be sure if isExplicit is returning the true state of
+ * affairs is if it returns false. An implicitly tagged object may appear
+ * to be explicitly tagged, so you need to understand the context under
+ * which the reading was done as well, see getObject below.
+ */
+ public boolean isExplicit()
+ {
+ return explicit;
+ }
+
+ public boolean isEmpty()
+ {
+ return empty;
+ }
+
+ /**
+ * return whatever was following the tag.
+ *
+ * Note: tagged objects are generally context dependent if you're
+ * trying to extract a tagged object you should be going via the
+ * appropriate getInstance method.
+ */
+ public DERObject getObject()
+ {
+ if (obj != null)
+ {
+ return obj.getDERObject();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the object held in this tagged object as a parser assuming it has
+ * the type of the passed in tag. If the object doesn't have a parser
+ * associated with it, the base object is returned.
+ */
+ public DEREncodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ {
+ switch (tag)
+ {
+ case DERTags.SET:
+ return ASN1Set.getInstance(this, isExplicit).parser();
+ case DERTags.SEQUENCE:
+ return ASN1Sequence.getInstance(this, isExplicit).parser();
+ case DERTags.OCTET_STRING:
+ return ASN1OctetString.getInstance(this, isExplicit).parser();
+ }
+
+ if (isExplicit)
+ {
+ return getObject();
+ }
+
+ throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
+ }
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "[" + tagNo + "]" + obj;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
new file mode 100644
index 00000000..5574bf83
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
@@ -0,0 +1,12 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1TaggedObjectParser
+ extends DEREncodable
+{
+ public int getTagNo();
+
+ public DEREncodable getObjectParser(int tag, boolean isExplicit)
+ throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecific.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecific.java
new file mode 100644
index 00000000..8bc8a4eb
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecific.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.asn1;
+
+public class BERApplicationSpecific
+ extends DERApplicationSpecific
+{
+ public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ super(tagNo, vec);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecificParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecificParser.java
new file mode 100644
index 00000000..0c46ba34
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERApplicationSpecificParser.java
@@ -0,0 +1,34 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERApplicationSpecificParser
+ implements ASN1ApplicationSpecificParser
+{
+ private final int tag;
+ private final ASN1StreamParser parser;
+
+ BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
+ {
+ this.tag = tag;
+ this.parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new BERApplicationSpecific(tag, parser.readVector());
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedOctetString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedOctetString.java
new file mode 100644
index 00000000..dfa8ac47
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedOctetString.java
@@ -0,0 +1,145 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+@SuppressWarnings("unchecked")
+public class BERConstructedOctetString
+ extends DEROctetString
+{
+ private static final int MAX_LENGTH = 1000;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ static private byte[] toBytes(
+ Vector octs)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != octs.size(); i++)
+ {
+ try
+ {
+ DEROctetString o = (DEROctetString)octs.elementAt(i);
+
+ bOut.write(o.getOctets());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("exception converting octets " + e.toString());
+ }
+ }
+
+ return bOut.toByteArray();
+ }
+
+ private Vector octs;
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public BERConstructedOctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public BERConstructedOctetString(
+ Vector octs)
+ {
+ super(toBytes(octs));
+
+ this.octs = octs;
+ }
+
+ public BERConstructedOctetString(
+ DERObject obj)
+ {
+ super(obj);
+ }
+
+ public BERConstructedOctetString(
+ DEREncodable obj)
+ {
+ super(obj.getDERObject());
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public Enumeration getObjects()
+ {
+ if (octs == null)
+ {
+ return generateOcts().elements();
+ }
+
+ return octs.elements();
+ }
+
+ private Vector generateOcts()
+ {
+ Vector vec = new Vector();
+ for (int i = 0; i < string.length; i += MAX_LENGTH)
+ {
+ int end;
+
+ if (i + MAX_LENGTH > string.length)
+ {
+ end = string.length;
+ }
+ else
+ {
+ end = i + MAX_LENGTH;
+ }
+
+ byte[] nStr = new byte[end - i];
+
+ System.arraycopy(string, i, nStr, 0, nStr.length);
+
+ vec.addElement(new DEROctetString(nStr));
+ }
+
+ return vec;
+ }
+
+ public void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.write(CONSTRUCTED | OCTET_STRING);
+
+ out.write(0x80);
+
+ //
+ // write out the octet array
+ //
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject(e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedSequence.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedSequence.java
new file mode 100644
index 00000000..9e1d6a59
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERConstructedSequence.java
@@ -0,0 +1,38 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * @deprecated use BERSequence
+ */
+@SuppressWarnings("unchecked")
+public class BERConstructedSequence
+ extends DERConstructedSequence
+{
+ /*
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.write(SEQUENCE | CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject(e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERFactory.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERFactory.java
new file mode 100644
index 00000000..82f101c7
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERFactory.java
@@ -0,0 +1,22 @@
+package org.bouncycastle.asn1;
+
+class BERFactory
+{
+ static final BERSequence EMPTY_SEQUENCE = new BERSequence();
+ static final BERSet EMPTY_SET = new BERSet();
+
+ static BERSequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
+ }
+
+ static BERSet createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new BERSet(v);
+ }
+
+ static BERSet createSet(ASN1EncodableVector v, boolean needsSorting)
+ {
+ return v.size() < 1 ? EMPTY_SET : new BERSet(v, needsSorting);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERGenerator.java
new file mode 100644
index 00000000..6b327419
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERGenerator.java
@@ -0,0 +1,100 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class BERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected BERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public BERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _out;
+ }
+
+ private void writeHdr(
+ int tag)
+ throws IOException
+ {
+ _out.write(tag);
+ _out.write(0x80);
+ }
+
+ protected void writeBERHeader(
+ int tag)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | DERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ writeHdr(tagNum | DERTags.CONSTRUCTED);
+ writeHdr(tag);
+ }
+ else
+ {
+ if ((tag & DERTags.CONSTRUCTED) != 0)
+ {
+ writeHdr(tagNum | DERTags.CONSTRUCTED);
+ }
+ else
+ {
+ writeHdr(tagNum);
+ }
+ }
+ }
+ else
+ {
+ writeHdr(tag);
+ }
+ }
+
+ protected void writeBERBody(
+ InputStream contentStream)
+ throws IOException
+ {
+ int ch;
+
+ while ((ch = contentStream.read()) >= 0)
+ {
+ _out.write(ch);
+ }
+ }
+
+ protected void writeBEREnd()
+ throws IOException
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+
+ if (_tagged && _isExplicit) // write extra end for tag header
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERInputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERInputStream.java
new file mode 100644
index 00000000..1dfa06d9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERInputStream.java
@@ -0,0 +1,210 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Vector;
+
+/**
+ * @deprecated use ASN1InputStream
+ */
+@SuppressWarnings("unchecked")
+public class BERInputStream
+ extends DERInputStream
+{
+ private static final DERObject END_OF_STREAM = new DERObject()
+ {
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ throw new IOException("Eeek!");
+ }
+ public int hashCode()
+ {
+ return 0;
+ }
+ public boolean equals(
+ Object o)
+ {
+ return o == this;
+ }
+ };
+ public BERInputStream(
+ InputStream is)
+ {
+ super(is);
+ }
+
+ /**
+ * read a string of bytes representing an indefinite length object.
+ */
+ private byte[] readIndefiniteLengthFully()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ int b, b1;
+
+ b1 = read();
+
+ while ((b = read()) >= 0)
+ {
+ if (b1 == 0 && b == 0)
+ {
+ break;
+ }
+
+ bOut.write(b1);
+ b1 = b;
+ }
+
+ return bOut.toByteArray();
+ }
+
+ private BERConstructedOctetString buildConstructedOctetString()
+ throws IOException
+ {
+ Vector octs = new Vector();
+
+ for (;;)
+ {
+ DERObject o = readObject();
+
+ if (o == END_OF_STREAM)
+ {
+ break;
+ }
+
+ octs.addElement(o);
+ }
+
+ return new BERConstructedOctetString(octs);
+ }
+
+ public DERObject readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag == -1)
+ {
+ throw new EOFException();
+ }
+
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ switch (tag)
+ {
+ case NULL:
+ return null;
+ case SEQUENCE | CONSTRUCTED:
+ BERConstructedSequence seq = new BERConstructedSequence();
+
+ for (;;)
+ {
+ DERObject obj = readObject();
+
+ if (obj == END_OF_STREAM)
+ {
+ break;
+ }
+
+ seq.addObject(obj);
+ }
+ return seq;
+ case OCTET_STRING | CONSTRUCTED:
+ return buildConstructedOctetString();
+ case SET | CONSTRUCTED:
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (;;)
+ {
+ DERObject obj = readObject();
+
+ if (obj == END_OF_STREAM)
+ {
+ break;
+ }
+
+ v.add(obj);
+ }
+ return new BERSet(v);
+ default:
+ //
+ // with tagged object tag number is bottom 5 bits
+ //
+ if ((tag & TAGGED) != 0)
+ {
+ if ((tag & 0x1f) == 0x1f)
+ {
+ throw new IOException("unsupported high tag encountered");
+ }
+
+ //
+ // simple type - implicit... return an octet string
+ //
+ if ((tag & CONSTRUCTED) == 0)
+ {
+ byte[] bytes = readIndefiniteLengthFully();
+
+ return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
+ }
+
+ //
+ // either constructed or explicitly tagged
+ //
+ DERObject dObj = readObject();
+
+ if (dObj == END_OF_STREAM) // empty tag!
+ {
+ return new DERTaggedObject(tag & 0x1f);
+ }
+
+ DERObject next = readObject();
+
+ //
+ // explicitly tagged (probably!) - if it isn't we'd have to
+ // tell from the context
+ //
+ if (next == END_OF_STREAM)
+ {
+ return new BERTaggedObject(tag & 0x1f, dObj);
+ }
+
+ //
+ // another implicit object, we'll create a sequence...
+ //
+ seq = new BERConstructedSequence();
+
+ seq.addObject(dObj);
+
+ do
+ {
+ seq.addObject(next);
+ next = readObject();
+ }
+ while (next != END_OF_STREAM);
+
+ return new BERTaggedObject(false, tag & 0x1f, seq);
+ }
+
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ if (tag == 0 && length == 0) // end of contents marker.
+ {
+ return END_OF_STREAM;
+ }
+
+ byte[] bytes = new byte[length];
+
+ readFully(bytes);
+
+ return buildObject(tag, bytes);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERNull.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERNull.java
new file mode 100644
index 00000000..92bc10da
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERNull.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A BER NULL object.
+ */
+public class BERNull
+ extends DERNull
+{
+ public static final BERNull INSTANCE = new BERNull();
+
+ public BERNull()
+ {
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.write(NULL);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringGenerator.java
new file mode 100644
index 00000000..61ef8245
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringGenerator.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROctetStringGenerator
+ extends BERGenerator
+{
+ public BEROctetStringGenerator(OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
+ }
+
+ public BEROctetStringGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
+ }
+
+ public OutputStream getOctetOutputStream()
+ {
+ return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
+ }
+
+ public OutputStream getOctetOutputStream(
+ byte[] buf)
+ {
+ return new BufferedBEROctetStream(buf);
+ }
+
+ private class BufferedBEROctetStream
+ extends OutputStream
+ {
+ private byte[] _buf;
+ private int _off;
+ private DEROutputStream _derOut;
+
+ BufferedBEROctetStream(
+ byte[] buf)
+ {
+ _buf = buf;
+ _off = 0;
+ _derOut = new DEROutputStream(_out);
+ }
+
+ public void write(
+ int b)
+ throws IOException
+ {
+ _buf[_off++] = (byte)b;
+
+ if (_off == _buf.length)
+ {
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+ }
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ while (len > 0)
+ {
+ int numToCopy = Math.min(len, _buf.length - _off);
+ System.arraycopy(b, off, _buf, _off, numToCopy);
+
+ _off += numToCopy;
+ if (_off < _buf.length)
+ {
+ break;
+ }
+
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+
+ off += numToCopy;
+ len -= numToCopy;
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ if (_off != 0)
+ {
+ byte[] bytes = new byte[_off];
+ System.arraycopy(_buf, 0, bytes, 0, _off);
+
+ DEROctetString.encode(_derOut, bytes);
+ }
+
+ writeBEREnd();
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringParser.java
new file mode 100644
index 00000000..bc937ad9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROctetStringParser.java
@@ -0,0 +1,44 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.io.Streams;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+public class BEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private ASN1StreamParser _parser;
+
+ BEROctetStringParser(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ /**
+ * @deprecated will be removed
+ */
+ protected BEROctetStringParser(
+ ASN1ObjectParser parser)
+ {
+ _parser = parser._aIn;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return new ConstructedOctetStream(_parser);
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new BERConstructedOctetString(Streams.readAll(getOctetStream()));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROutputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROutputStream.java
new file mode 100644
index 00000000..c2e8da45
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BEROutputStream.java
@@ -0,0 +1,36 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROutputStream
+ extends DEROutputStream
+{
+ public BEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ Object obj)
+ throws IOException
+ {
+ if (obj == null)
+ {
+ writeNull();
+ }
+ else if (obj instanceof DERObject)
+ {
+ ((DERObject)obj).encode(this);
+ }
+ else if (obj instanceof DEREncodable)
+ {
+ ((DEREncodable)obj).getDERObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("object not BEREncodable");
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequence.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequence.java
new file mode 100644
index 00000000..5054fb52
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequence.java
@@ -0,0 +1,60 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+@SuppressWarnings("unchecked")
+public class BERSequence
+ extends DERSequence
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public BERSequence(
+ DEREncodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public BERSequence(
+ DEREncodableVector v)
+ {
+ super(v);
+ }
+
+ /*
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.write(SEQUENCE | CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject(e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceGenerator.java
new file mode 100644
index 00000000..bc634205
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceGenerator.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BERSequenceGenerator
+ extends BERGenerator
+{
+ public BERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
+ }
+
+ public BERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
+ }
+
+ public void addObject(
+ DEREncodable object)
+ throws IOException
+ {
+ object.getDERObject().encode(new BEROutputStream(_out));
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeBEREnd();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceParser.java
new file mode 100644
index 00000000..cd0ca279
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSequenceParser.java
@@ -0,0 +1,32 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new BERSequence(_parser.readVector());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSet.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSet.java
new file mode 100644
index 00000000..9f332029
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSet.java
@@ -0,0 +1,70 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+@SuppressWarnings("unchecked")
+public class BERSet
+ extends DERSet
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSet()
+ {
+ }
+
+ /**
+ * create a set containing one object
+ */
+ public BERSet(
+ DEREncodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public BERSet(
+ DEREncodableVector v)
+ {
+ super(v, false);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ BERSet(
+ DEREncodableVector v,
+ boolean needsSorting)
+ {
+ super(v, needsSorting);
+ }
+
+ /*
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.write(SET | CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject(e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSetParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSetParser.java
new file mode 100644
index 00000000..ac280d3f
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERSetParser.java
@@ -0,0 +1,32 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new BERSet(_parser.readVector(), false);
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObject.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObject.java
new file mode 100644
index 00000000..990c1432
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObject.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * BER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+@SuppressWarnings("unchecked")
+public class BERTaggedObject
+ extends DERTaggedObject
+{
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ int tagNo,
+ DEREncodable obj)
+ {
+ super(tagNo, obj);
+ }
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ DEREncodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public BERTaggedObject(
+ int tagNo)
+ {
+ super(false, tagNo, new BERSequence());
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
+ {
+ out.writeTag(CONSTRUCTED | TAGGED, tagNo);
+ out.write(0x80);
+
+ if (!empty)
+ {
+ if (!explicit)
+ {
+ Enumeration e;
+ if (obj instanceof ASN1OctetString)
+ {
+ if (obj instanceof BERConstructedOctetString)
+ {
+ e = ((BERConstructedOctetString)obj).getObjects();
+ }
+ else
+ {
+ ASN1OctetString octs = (ASN1OctetString)obj;
+ BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets());
+ e = berO.getObjects();
+ }
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ e = ((ASN1Sequence)obj).getObjects();
+ }
+ else if (obj instanceof ASN1Set)
+ {
+ e = ((ASN1Set)obj).getObjects();
+ }
+ else
+ {
+ throw new RuntimeException("not implemented: " + obj.getClass().getName());
+ }
+
+ while (e.hasMoreElements())
+ {
+ out.writeObject(e.nextElement());
+ }
+ }
+ else
+ {
+ out.writeObject(obj);
+ }
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+ else
+ {
+ super.encode(out);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObjectParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObjectParser.java
new file mode 100644
index 00000000..ce7318d2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/BERTaggedObjectParser.java
@@ -0,0 +1,123 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BERTaggedObjectParser
+ implements ASN1TaggedObjectParser
+{
+ private int _baseTag;
+ private int _tagNumber;
+ private InputStream _contentStream;
+
+ private boolean _indefiniteLength;
+
+ protected BERTaggedObjectParser(
+ int baseTag,
+ int tagNumber,
+ InputStream contentStream)
+ {
+ _baseTag = baseTag;
+ _tagNumber = tagNumber;
+ _contentStream = contentStream;
+ _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
+ }
+
+ public boolean isConstructed()
+ {
+ return (_baseTag & DERTags.CONSTRUCTED) != 0;
+ }
+
+ public int getTagNo()
+ {
+ return _tagNumber;
+ }
+
+ public DEREncodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ throws IOException
+ {
+ if (isExplicit)
+ {
+ return new ASN1StreamParser(_contentStream).readObject();
+ }
+
+ switch (tag)
+ {
+ case DERTags.SET:
+ if (_indefiniteLength)
+ {
+ return new BERSetParser(new ASN1StreamParser(_contentStream));
+ }
+ else
+ {
+ return new DERSetParser(new ASN1StreamParser(_contentStream));
+ }
+ case DERTags.SEQUENCE:
+ if (_indefiniteLength)
+ {
+ return new BERSequenceParser(new ASN1StreamParser(_contentStream));
+ }
+ else
+ {
+ return new DERSequenceParser(new ASN1StreamParser(_contentStream));
+ }
+ case DERTags.OCTET_STRING:
+ // TODO Is the handling of definite length constructed encodings correct?
+ if (_indefiniteLength || this.isConstructed())
+ {
+ return new BEROctetStringParser(new ASN1StreamParser(_contentStream));
+ }
+ else
+ {
+ return new DEROctetStringParser((DefiniteLengthInputStream)_contentStream);
+ }
+ }
+
+ throw new RuntimeException("implicit tagging not implemented");
+ }
+
+ private ASN1EncodableVector rLoadVector(InputStream in)
+ {
+ try
+ {
+ return new ASN1StreamParser(in).readVector();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+
+ public DERObject getDERObject()
+ {
+ if (_indefiniteLength)
+ {
+ ASN1EncodableVector v = rLoadVector(_contentStream);
+
+ return v.size() == 1
+ ? new BERTaggedObject(true, _tagNumber, v.get(0))
+ : new BERTaggedObject(false, _tagNumber, BERFactory.createSequence(v));
+ }
+
+ if (this.isConstructed())
+ {
+ ASN1EncodableVector v = rLoadVector(_contentStream);
+
+ return v.size() == 1
+ ? new DERTaggedObject(true, _tagNumber, v.get(0))
+ : new DERTaggedObject(false, _tagNumber, DERFactory.createSequence(v));
+ }
+
+ try
+ {
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_contentStream;
+ return new DERTaggedObject(false, _tagNumber, new DEROctetString(defIn.toByteArray()));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ConstructedOctetStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ConstructedOctetStream.java
new file mode 100644
index 00000000..045cffda
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ConstructedOctetStream.java
@@ -0,0 +1,111 @@
+package org.bouncycastle.asn1;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+class ConstructedOctetStream
+ extends InputStream
+{
+ private final ASN1StreamParser _parser;
+
+ private boolean _first = true;
+ private InputStream _currentStream;
+
+ ConstructedOctetStream(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
+
+ if (numRead >= 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == len)
+ {
+ return totalRead;
+ }
+ }
+ else
+ {
+ ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
+
+ if (aos == null)
+ {
+ _currentStream = null;
+ return totalRead < 1 ? -1 : totalRead;
+ }
+
+ _currentStream = aos.getOctetStream();
+ }
+ }
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ for (;;)
+ {
+ int b = _currentStream.read();
+
+ if (b >= 0)
+ {
+ return b;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ _currentStream = null;
+ return -1;
+ }
+
+ _currentStream = s.getOctetStream();
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERApplicationSpecific.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERApplicationSpecific.java
new file mode 100644
index 00000000..7ca06d6a
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERApplicationSpecific.java
@@ -0,0 +1,225 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * Base class for an application specific object
+ */
+public class DERApplicationSpecific
+ extends ASN1Object
+{
+ private final boolean isConstructed;
+ private final int tag;
+ private final byte[] octets;
+
+ DERApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ DEREncodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ public DERApplicationSpecific(
+ boolean explicit,
+ int tag,
+ DEREncodable object)
+ throws IOException
+ {
+ byte[] data = object.getDERObject().getDEREncoded();
+
+ this.isConstructed = explicit;
+ this.tag = tag;
+
+ if (explicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfLength(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ this.octets = tmp;
+ }
+ }
+
+ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Encodable)vec.get(i)).getEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ this.octets = bOut.toByteArray();
+ }
+
+ private int getLengthOfLength(byte[] data)
+ {
+ int count = 2; // TODO: assumes only a 1 byte tag number
+
+ while((data[count - 1] & 0x80) != 0)
+ {
+ count++;
+ }
+
+ return count;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] getContents()
+ {
+ return octets;
+ }
+
+ public int getApplicationTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public DERObject getObject()
+ throws IOException
+ {
+ return new ASN1InputStream(getContents()).readObject();
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public DERObject getObject(int derTagNo)
+ throws IOException
+ {
+ if (derTagNo >= 0x1f)
+ {
+ throw new IOException("unsupported tag number");
+ }
+
+ byte[] orig = this.getEncoded();
+ byte[] tmp = replaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & DERTags.CONSTRUCTED) != 0)
+ {
+ tmp[0] |= DERTags.CONSTRUCTED;
+ }
+
+ return new ASN1InputStream(tmp).readObject();
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(DEROutputStream out) throws IOException
+ {
+ int classBits = DERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= DERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERApplicationSpecific))
+ {
+ return false;
+ }
+
+ DERApplicationSpecific other = (DERApplicationSpecific)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(octets, other.octets);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
+ }
+
+ private byte[] replaceTagNumber(int newTag, byte[] input)
+ throws IOException
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = input[index++] & 0xff;
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = input[index++] & 0xff;
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ byte[] tmp = new byte[input.length - index + 1];
+
+ System.arraycopy(input, index, tmp, 1, tmp.length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBMPString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBMPString.java
new file mode 100644
index 00000000..14723254
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBMPString.java
@@ -0,0 +1,126 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER BMPString object.
+ */
+public class DERBMPString
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a BMP String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERBMPString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBMPString)
+ {
+ return (DERBMPString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERBMPString(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a BMP 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.
+ */
+ public static DERBMPString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERBMPString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length / 2];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERBMPString(
+ String string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ protected boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERBMPString))
+ {
+ return false;
+ }
+
+ DERBMPString s = (DERBMPString)o;
+
+ return this.getString().equals(s.getString());
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ char[] c = string.toCharArray();
+ byte[] b = new byte[c.length * 2];
+
+ for (int i = 0; i != c.length; i++)
+ {
+ b[2 * i] = (byte)(c[i] >> 8);
+ b[2 * i + 1] = (byte)c[i];
+ }
+
+ out.writeEncoded(BMP_STRING, b);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBitString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBitString.java
new file mode 100644
index 00000000..efcdaca7
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBitString.java
@@ -0,0 +1,266 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.Arrays;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class DERBitString
+ extends ASN1Object
+ implements DERString
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ protected byte[] data;
+ protected int padBits;
+
+ /**
+ * return the correct number of pad bits for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected int getPadBits(
+ int bitString)
+ {
+ int val = 0;
+ for (int i = 3; i >= 0; i--)
+ {
+ //
+ // this may look a little odd, but if it isn't done like this pre jdk1.2
+ // JVM's break!
+ //
+ if (i != 0)
+ {
+ if ((bitString >> (i * 8)) != 0)
+ {
+ val = (bitString >> (i * 8)) & 0xFF;
+ break;
+ }
+ }
+ else
+ {
+ if (bitString != 0)
+ {
+ val = bitString & 0xFF;
+ break;
+ }
+ }
+ }
+
+ if (val == 0)
+ {
+ return 7;
+ }
+
+
+ int bits = 1;
+
+ while (((val <<= 1) & 0xFF) != 0)
+ {
+ bits++;
+ }
+
+ return 8 - bits;
+ }
+
+ /**
+ * return the correct number of bytes for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected byte[] getBytes(int bitString)
+ {
+ int bytes = 4;
+ for (int i = 3; i >= 1; i--)
+ {
+ if ((bitString & (0xFF << (i * 8))) != 0)
+ {
+ break;
+ }
+ bytes--;
+ }
+
+ byte[] result = new byte[bytes];
+ for (int i = 0; i < bytes; i++)
+ {
+ result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+ }
+
+ return result;
+ }
+
+ /**
+ * return a Bit String from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERBitString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBitString)
+ {
+ return (DERBitString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ byte[] bytes = ((ASN1OctetString)obj).getOctets();
+ int padBits = bytes[0];
+ byte[] data = new byte[bytes.length - 1];
+
+ System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+
+ return new DERBitString(data, padBits);
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Bit 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.
+ */
+ public static DERBitString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ protected DERBitString(
+ byte data,
+ int padBits)
+ {
+ this.data = new byte[1];
+ this.data[0] = data;
+ this.padBits = padBits;
+ }
+
+ /**
+ * @param data the octets making up the bit string.
+ * @param padBits the number of extra bits at the end of the string.
+ */
+ public DERBitString(
+ byte[] data,
+ int padBits)
+ {
+ this.data = data;
+ this.padBits = padBits;
+ }
+
+ public DERBitString(
+ byte[] data)
+ {
+ this(data, 0);
+ }
+
+ public DERBitString(
+ DEREncodable obj)
+ {
+ try
+ {
+ this.data = obj.getDERObject().getEncoded(ASN1Encodable.DER);
+ this.padBits = 0;
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Error processing object : " + e.toString());
+ }
+ }
+
+ public byte[] getBytes()
+ {
+ return data;
+ }
+
+ public int getPadBits()
+ {
+ return padBits;
+ }
+
+
+ /**
+ * @return the value of the bit string as an int (truncating if necessary)
+ */
+ public int intValue()
+ {
+ int value = 0;
+
+ for (int i = 0; i != data.length && i != 4; i++)
+ {
+ value |= (data[i] & 0xff) << (8 * i);
+ }
+
+ return value;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ byte[] bytes = new byte[getBytes().length + 1];
+
+ bytes[0] = (byte)getPadBits();
+ System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
+
+ out.writeEncoded(BIT_STRING, bytes);
+ }
+
+ public int hashCode()
+ {
+ return padBits ^ Arrays.hashCode(data);
+ }
+
+ protected boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERBitString))
+ {
+ return false;
+ }
+
+ DERBitString other = (DERBitString)o;
+
+ return this.padBits == other.padBits
+ && Arrays.areEqual(this.data, other.data);
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBoolean.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBoolean.java
new file mode 100644
index 00000000..a2f0c4d4
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERBoolean.java
@@ -0,0 +1,113 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERBoolean
+ extends ASN1Object
+{
+ byte value;
+
+ public static final DERBoolean FALSE = new DERBoolean(false);
+ public static final DERBoolean TRUE = new DERBoolean(true);
+
+ /**
+ * return a boolean from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERBoolean getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBoolean)
+ {
+ return (DERBoolean)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERBoolean(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a DERBoolean from the passed in boolean.
+ */
+ public static DERBoolean getInstance(
+ boolean value)
+ {
+ return (value ? 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 DERBoolean getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public DERBoolean(
+ byte[] value)
+ {
+ this.value = value[0];
+ }
+
+ public DERBoolean(
+ boolean value)
+ {
+ this.value = (value) ? (byte)0xff : (byte)0;
+ }
+
+ public boolean isTrue()
+ {
+ return (value != 0);
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ byte[] bytes = new byte[1];
+
+ bytes[0] = value;
+
+ out.writeEncoded(BOOLEAN, bytes);
+ }
+
+ protected boolean asn1Equals(
+ DERObject o)
+ {
+ if ((o == null) || !(o instanceof DERBoolean))
+ {
+ return false;
+ }
+
+ return (value == ((DERBoolean)o).value);
+ }
+
+ public int hashCode()
+ {
+ return value;
+ }
+
+
+ public String toString()
+ {
+ return (value != 0) ? "TRUE" : "FALSE";
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSequence.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSequence.java
new file mode 100644
index 00000000..1011cb93
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSequence.java
@@ -0,0 +1,54 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * @deprecated use DERSequence.
+ */
+@SuppressWarnings("unchecked")
+public class DERConstructedSequence
+ extends ASN1Sequence
+{
+ public void addObject(
+ DEREncodable obj)
+ {
+ super.addObject(obj);
+ }
+
+ public int getSize()
+ {
+ return size();
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+ Enumeration e = this.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject(obj);
+ }
+
+ dOut.close();
+
+ byte[] bytes = bOut.toByteArray();
+
+ out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSet.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSet.java
new file mode 100644
index 00000000..656d56b2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERConstructedSet.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ *
+ * @deprecated use DERSet
+ */
+@SuppressWarnings("unchecked")
+public class DERConstructedSet
+ extends ASN1Set
+{
+ public DERConstructedSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DERConstructedSet(
+ DEREncodable obj)
+ {
+ this.addObject(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DERConstructedSet(
+ DEREncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ this.addObject(v.get(i));
+ }
+ }
+
+ public void addObject(
+ DEREncodable obj)
+ {
+ super.addObject(obj);
+ }
+
+ public int getSize()
+ {
+ return size();
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+ Enumeration e = this.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject(obj);
+ }
+
+ dOut.close();
+
+ byte[] bytes = bOut.toByteArray();
+
+ out.writeEncoded(SET | CONSTRUCTED, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodable.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodable.java
new file mode 100644
index 00000000..d89305a1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodable.java
@@ -0,0 +1,6 @@
+package org.bouncycastle.asn1;
+
+public interface DEREncodable
+{
+ public DERObject getDERObject();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodableVector.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodableVector.java
new file mode 100644
index 00000000..86a29450
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREncodableVector.java
@@ -0,0 +1,39 @@
+package org.bouncycastle.asn1;
+
+import java.util.Vector;
+
+/**
+ * a general class for building up a vector of DER encodable objects -
+ * this will eventually be superceded by ASN1EncodableVector so you should
+ * use that class in preference.
+ */
+@SuppressWarnings("unchecked")
+public class DEREncodableVector
+{
+ Vector v = new Vector();
+
+ /**
+ * @deprecated use ASN1EncodableVector instead.
+ */
+ public DEREncodableVector()
+ {
+
+ }
+
+ public void add(
+ DEREncodable obj)
+ {
+ v.addElement(obj);
+ }
+
+ public DEREncodable get(
+ int i)
+ {
+ return (DEREncodable)v.elementAt(i);
+ }
+
+ public int size()
+ {
+ return v.size();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREnumerated.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREnumerated.java
new file mode 100644
index 00000000..5a9da4c9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEREnumerated.java
@@ -0,0 +1,102 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.Arrays;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+public class DEREnumerated
+ extends ASN1Object
+{
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DEREnumerated getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DEREnumerated)
+ {
+ return (DEREnumerated)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DEREnumerated(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ 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 DEREnumerated getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public DEREnumerated(
+ int value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ public DEREnumerated(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ public DEREnumerated(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(ENUMERATED, bytes);
+ }
+
+ boolean asn1Equals(
+ DERObject 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);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternal.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternal.java
new file mode 100644
index 00000000..ad062c8b
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternal.java
@@ -0,0 +1,267 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Class representing the DER-type External
+ */
+public class DERExternal
+ extends ASN1Object
+{
+ private DERObjectIdentifier directReference;
+ private DERInteger indirectReference;
+ private ASN1Object dataValueDescriptor;
+ private int encoding;
+ private DERObject externalContent;
+
+ public DERExternal(ASN1EncodableVector vector)
+ {
+ int offset = 0;
+ DERObject enc = vector.get(offset).getDERObject();
+ if (enc instanceof DERObjectIdentifier)
+ {
+ directReference = (DERObjectIdentifier)enc;
+ offset++;
+ enc = vector.get(offset).getDERObject();
+ }
+ if (enc instanceof DERInteger)
+ {
+ indirectReference = (DERInteger) enc;
+ offset++;
+ enc = vector.get(offset).getDERObject();
+ }
+ if (!(enc instanceof DERTaggedObject))
+ {
+ dataValueDescriptor = (ASN1Object) enc;
+ offset++;
+ enc = vector.get(offset).getDERObject();
+ }
+ if (!(enc instanceof DERTaggedObject))
+ {
+ throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
+ }
+ DERTaggedObject obj = (DERTaggedObject)enc;
+ setEncoding(obj.getTagNo());
+ externalContent = obj.getObject();
+ }
+
+ /**
+ * Creates a new instance of DERExternal
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ // TODO Intermediate buffer could be avoided if we could calculate expected length
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+ Enumeration e = this.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject(obj);
+ }
+
+ dOut.close();
+
+ byte[] bytes = bOut.toByteArray();
+
+ out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceGenerator.java
new file mode 100644
index 00000000..458dcdc8
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceGenerator.java
@@ -0,0 +1,45 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DERSequenceGenerator
+ extends DERGenerator
+{
+ private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
+
+ public DERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+ }
+
+ public DERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+ }
+
+ public void addObject(
+ DEREncodable object)
+ throws IOException
+ {
+ object.getDERObject().encode(new DEROutputStream(_bOut));
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _bOut;
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeDEREncoded(DERTags.CONSTRUCTED | DERTags.SEQUENCE, _bOut.toByteArray());
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceParser.java
new file mode 100644
index 00000000..59ba7f74
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequenceParser.java
@@ -0,0 +1,32 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new DERSequence(_parser.readVector());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSet.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSet.java
new file mode 100644
index 00000000..2634e13d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSet.java
@@ -0,0 +1,101 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * A DER encoded set object
+ */
+@SuppressWarnings("unchecked")
+public class DERSet
+ extends ASN1Set
+{
+ /**
+ * create an empty set
+ */
+ public DERSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DERSet(
+ DEREncodable obj)
+ {
+ this.addObject(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DERSet(
+ DEREncodableVector v)
+ {
+ this(v, true);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public DERSet(
+ ASN1Encodable[] a)
+ {
+ for (int i = 0; i != a.length; i++)
+ {
+ this.addObject(a[i]);
+ }
+
+ this.sort();
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ DERSet(
+ DEREncodableVector v,
+ boolean needsSorting)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ this.addObject(v.get(i));
+ }
+
+ if (needsSorting)
+ {
+ this.sort();
+ }
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ // TODO Intermediate buffer could be avoided if we could calculate expected length
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+ Enumeration e = this.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject(obj);
+ }
+
+ dOut.close();
+
+ byte[] bytes = bOut.toByteArray();
+
+ out.writeEncoded(SET | CONSTRUCTED, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSetParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSetParser.java
new file mode 100644
index 00000000..2793e516
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSetParser.java
@@ -0,0 +1,32 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new DERSet(_parser.readVector(), false);
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERString.java
new file mode 100644
index 00000000..3143be9b
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERString.java
@@ -0,0 +1,9 @@
+package org.bouncycastle.asn1;
+
+/**
+ * basic interface for DER string objects.
+ */
+public interface DERString
+{
+ public String getString();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERT61String.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERT61String.java
new file mode 100644
index 00000000..09039fc3
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERT61String.java
@@ -0,0 +1,126 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER T61String (also the teletex string)
+ */
+public class DERT61String
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a T61 string from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERT61String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERT61String)
+ {
+ return (DERT61String)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERT61String(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an T61 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.
+ */
+ public static DERT61String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DERT61String(
+ byte[] string)
+ {
+ char[] cs = new char[string.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor - with string.
+ */
+ public DERT61String(
+ String string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(T61_STRING, this.getOctets());
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERT61String))
+ {
+ return false;
+ }
+
+ return this.getString().equals(((DERT61String)o).getString());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTaggedObject.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTaggedObject.java
new file mode 100644
index 00000000..a1d36878
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTaggedObject.java
@@ -0,0 +1,85 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class DERTaggedObject
+ extends ASN1TaggedObject
+{
+ private static final byte[] ZERO_BYTES = new byte[0];
+
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DERTaggedObject(
+ int tagNo,
+ DEREncodable obj)
+ {
+ super(tagNo, obj);
+ }
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ DEREncodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public DERTaggedObject(
+ int tagNo)
+ {
+ super(false, tagNo, new DERSequence());
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ if (!empty)
+ {
+ byte[] bytes = obj.getDERObject().getEncoded(DER);
+
+ if (explicit)
+ {
+ out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, bytes);
+ }
+ else
+ {
+ //
+ // need to mark constructed types...
+ //
+ int flags;
+ if ((bytes[0] & CONSTRUCTED) != 0)
+ {
+ flags = CONSTRUCTED | TAGGED;
+ }
+ else
+ {
+ flags = TAGGED;
+ }
+
+ out.writeTag(flags, tagNo);
+ out.write(bytes, 1, bytes.length - 1);
+ }
+ }
+ else
+ {
+ out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, ZERO_BYTES);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTags.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTags.java
new file mode 100644
index 00000000..ef441ef6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERTags.java
@@ -0,0 +1,36 @@
+package org.bouncycastle.asn1;
+
+public interface DERTags
+{
+ public static final int BOOLEAN = 0x01;
+ public static final int INTEGER = 0x02;
+ public static final int BIT_STRING = 0x03;
+ public static final int OCTET_STRING = 0x04;
+ public static final int NULL = 0x05;
+ public static final int OBJECT_IDENTIFIER = 0x06;
+ public static final int EXTERNAL = 0x08;
+ public static final int ENUMERATED = 0x0a;
+ public static final int SEQUENCE = 0x10;
+ public static final int SEQUENCE_OF = 0x10; // for completeness
+ public static final int SET = 0x11;
+ public static final int SET_OF = 0x11; // for completeness
+
+
+ public static final int NUMERIC_STRING = 0x12;
+ public static final int PRINTABLE_STRING = 0x13;
+ public static final int T61_STRING = 0x14;
+ public static final int VIDEOTEX_STRING = 0x15;
+ public static final int IA5_STRING = 0x16;
+ public static final int UTC_TIME = 0x17;
+ public static final int GENERALIZED_TIME = 0x18;
+ public static final int GRAPHIC_STRING = 0x19;
+ public static final int VISIBLE_STRING = 0x1a;
+ public static final int GENERAL_STRING = 0x1b;
+ public static final int UNIVERSAL_STRING = 0x1c;
+ public static final int BMP_STRING = 0x1e;
+ public static final int UTF8_STRING = 0x0c;
+
+ public static final int CONSTRUCTED = 0x20;
+ public static final int APPLICATION = 0x40;
+ public static final int TAGGED = 0x80;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTCTime.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTCTime.java
new file mode 100644
index 00000000..7a056647
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTCTime.java
@@ -0,0 +1,254 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+/**
+ * UTC time object.
+ */
+public class DERUTCTime
+ extends ASN1Object
+{
+ String time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERUTCTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERUTCTime)
+ {
+ return (DERUTCTime)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERUTCTime(((ASN1OctetString)obj).getOctets());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * 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 DERUTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * 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 = time;
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructer from a java.util.date object
+ */
+ public DERUTCTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = dateF.format(time);
+ }
+
+ DERUTCTime(
+ byte[] bytes)
+ {
+ //
+ // explicitly convert to characters
+ //
+ char[] dateC = new char[bytes.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)(bytes[i] & 0xff);
+ }
+
+ this.time = new String(dateC);
+ }
+
+ /**
+ * 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:
+ *
+ * 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()
+ {
+ //
+ // standardise the format.
+ //
+ if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
+ {
+ if (time.length() == 11)
+ {
+ return time.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return time.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = time.indexOf('-');
+ if (index < 0)
+ {
+ index = time.indexOf('+');
+ }
+ String d = time;
+
+ if (index == time.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;
+ }
+ }
+
+ private byte[] getOctets()
+ {
+ char[] cs = time.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(UTC_TIME, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERUTCTime))
+ {
+ return false;
+ }
+
+ return time.equals(((DERUTCTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return time.hashCode();
+ }
+
+ public String toString()
+ {
+ return time;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTF8String.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTF8String.java
new file mode 100644
index 00000000..082aa636
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUTF8String.java
@@ -0,0 +1,109 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.Strings;
+
+import java.io.IOException;
+
+/**
+ * DER UTF8String object.
+ */
+public class DERUTF8String
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return an UTF8 string from the passed in object.
+ *
+ * @exception IllegalArgumentException
+ * if the object cannot be converted.
+ */
+ public static DERUTF8String getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERUTF8String)
+ {
+ return (DERUTF8String)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERUTF8String(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTF8 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.
+ */
+ public static DERUTF8String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERUTF8String(byte[] string)
+ {
+ this.string = Strings.fromUTF8ByteArray(string);
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERUTF8String(String string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ boolean asn1Equals(DERObject o)
+ {
+ if (!(o instanceof DERUTF8String))
+ {
+ return false;
+ }
+
+ DERUTF8String s = (DERUTF8String)o;
+
+ return this.getString().equals(s.getString());
+ }
+
+ void encode(DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string));
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUniversalString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUniversalString.java
new file mode 100644
index 00000000..68be9a01
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUniversalString.java
@@ -0,0 +1,120 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * DER UniversalString object.
+ */
+public class DERUniversalString
+ extends ASN1Object
+ implements DERString
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ private byte[] string;
+
+ /**
+ * return a Universal String from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERUniversalString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERUniversalString)
+ {
+ return (DERUniversalString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERUniversalString(((ASN1OctetString)obj).getOctets());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Universal 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.
+ */
+ public static DERUniversalString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERUniversalString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERUniversalString))
+ {
+ return false;
+ }
+
+ return this.getString().equals(((DERUniversalString)o).getString());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUnknownTag.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUnknownTag.java
new file mode 100644
index 00000000..1feed40f
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERUnknownTag.java
@@ -0,0 +1,79 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import org.bouncycastle.util.Arrays;
+
+/**
+ * We insert one of these when we find a tag we don't recognise.
+ */
+public class DERUnknownTag
+ extends DERObject
+{
+ private boolean isConstructed;
+ private int tag;
+ private byte[] data;
+
+ /**
+ * @param tag the tag value.
+ * @param data the contents octets.
+ */
+ public DERUnknownTag(
+ int tag,
+ byte[] data)
+ {
+ this(false, tag, data);
+ }
+
+ public DERUnknownTag(
+ boolean isConstructed,
+ int tag,
+ byte[] data)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.data = data;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public int getTag()
+ {
+ return tag;
+ }
+
+ public byte[] getData()
+ {
+ return data;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(isConstructed ? DERTags.CONSTRUCTED : 0, tag, data);
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DERUnknownTag))
+ {
+ return false;
+ }
+
+ DERUnknownTag other = (DERUnknownTag)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(data, other.data);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? ~0 : 0) ^ tag ^ Arrays.hashCode(data);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERVisibleString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERVisibleString.java
new file mode 100644
index 00000000..9d0c9915
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERVisibleString.java
@@ -0,0 +1,126 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER VisibleString object.
+ */
+public class DERVisibleString
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a Visible String from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERVisibleString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERVisibleString)
+ {
+ return (DERVisibleString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERVisibleString(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * 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.
+ */
+ public static DERVisibleString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERVisibleString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERVisibleString(
+ String string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(VISIBLE_STRING, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERVisibleString))
+ {
+ return false;
+ }
+
+ return this.getString().equals(((DERVisibleString)o).getString());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java
new file mode 100644
index 00000000..2a7f2e73
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java
@@ -0,0 +1,105 @@
+package org.bouncycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.util.io.Streams;
+
+class DefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private static final byte[] EMPTY_BYTES = new byte[0];
+
+ private final int _originalLength;
+ private int _remaining;
+
+ DefiniteLengthInputStream(
+ InputStream in,
+ int length)
+ {
+ super(in);
+
+ if (length < 0)
+ {
+ throw new IllegalArgumentException("negative lengths not allowed");
+ }
+
+ this._originalLength = length;
+ this._remaining = length;
+
+ if (length == 0)
+ {
+ setParentEofDetect(true);
+ }
+ }
+
+ int getRemaining()
+ {
+ return _remaining;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if (--_remaining == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return b;
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int toRead = Math.min(len, _remaining);
+ int numRead = _in.read(buf, off, toRead);
+
+ if (numRead < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if ((_remaining -= numRead) == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return numRead;
+ }
+
+ byte[] toByteArray()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
+ byte[] bytes = new byte[_remaining];
+ if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+ setParentEofDetect(true);
+ return bytes;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
new file mode 100644
index 00000000..d9eac066
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
@@ -0,0 +1,110 @@
+package org.bouncycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+class IndefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private int _b1;
+ private int _b2;
+ private boolean _eofReached = false;
+ private boolean _eofOn00 = true;
+
+ IndefiniteLengthInputStream(
+ InputStream in)
+ throws IOException
+ {
+ super(in);
+
+ _b1 = in.read();
+ _b2 = in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ checkForEof();
+ }
+
+ void setEofOn00(
+ boolean eofOn00)
+ {
+ _eofOn00 = eofOn00;
+ checkForEof();
+ }
+
+ private boolean checkForEof()
+ {
+ if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
+ {
+ _eofReached = true;
+ setParentEofDetect(true);
+ }
+ return _eofReached;
+ }
+
+ public int read(byte[] b, int off, int len)
+ throws IOException
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || len < 3)
+ {
+ return super.read(b, off, len);
+ }
+
+ if (_eofReached)
+ {
+ return -1;
+ }
+
+ int numRead = _in.read(b, off + 2, len - 2);
+
+ if (numRead < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ b[off] = (byte)_b1;
+ b[off + 1] = (byte)_b2;
+
+ _b1 = _in.read();
+ _b2 = _in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ return numRead + 2;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (checkForEof())
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ int v = _b1;
+
+ _b1 = _b2;
+ _b2 = b;
+
+ return v;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java
new file mode 100644
index 00000000..379c7bf1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java
@@ -0,0 +1,44 @@
+package org.bouncycastle.asn1;
+
+import java.util.Enumeration;
+import java.io.IOException;
+
+@SuppressWarnings("unchecked")
+class LazyDERConstructionEnumeration
+ implements Enumeration
+{
+ private ASN1InputStream aIn;
+ private Object nextObj;
+
+ public LazyDERConstructionEnumeration(byte[] encoded)
+ {
+ aIn = new ASN1InputStream(encoded, true);
+ nextObj = readObject();
+ }
+
+ public boolean hasMoreElements()
+ {
+ return nextObj != null;
+ }
+
+ public Object nextElement()
+ {
+ Object o = nextObj;
+
+ nextObj = readObject();
+
+ return o;
+ }
+
+ private Object readObject()
+ {
+ try
+ {
+ return aIn.readObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed DER construction: " + e, e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LimitedInputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LimitedInputStream.java
new file mode 100644
index 00000000..5a93335d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/LimitedInputStream.java
@@ -0,0 +1,23 @@
+package org.bouncycastle.asn1;
+
+import java.io.InputStream;
+
+abstract class LimitedInputStream
+ extends InputStream
+{
+ protected final InputStream _in;
+
+ LimitedInputStream(
+ InputStream in)
+ {
+ this._in = in;
+ }
+
+ protected void setParentEofDetect(boolean on)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(on);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/OIDTokenizer.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/OIDTokenizer.java
new file mode 100644
index 00000000..54679447
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/OIDTokenizer.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.asn1;
+
+/**
+ * class for breaking up an OID into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class OIDTokenizer
+{
+ private String oid;
+ private int index;
+
+ public OIDTokenizer(
+ String oid)
+ {
+ this.oid = oid;
+ this.index = 0;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != -1);
+ }
+
+ public String nextToken()
+ {
+ if (index == -1)
+ {
+ return null;
+ }
+
+ String token;
+ int end = oid.indexOf('.', index);
+
+ if (end == -1)
+ {
+ token = oid.substring(index);
+ index = -1;
+ return token;
+ }
+
+ token = oid.substring(index, end);
+
+ index = end + 1;
+ return token;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/ElGamalParameter.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/ElGamalParameter.java
new file mode 100644
index 00000000..21ffeeeb
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/ElGamalParameter.java
@@ -0,0 +1,50 @@
+package org.bouncycastle.asn1.oiw;
+
+import java.math.*;
+import java.util.*;
+
+import org.bouncycastle.asn1.*;
+
+@SuppressWarnings("unchecked")
+public class ElGamalParameter
+ extends ASN1Encodable
+{
+ DERInteger p, g;
+
+ public ElGamalParameter(
+ BigInteger p,
+ BigInteger g)
+ {
+ this.p = new DERInteger(p);
+ this.g = new DERInteger(g);
+ }
+
+ public ElGamalParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = (DERInteger)e.nextElement();
+ g = (DERInteger)e.nextElement();
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
new file mode 100644
index 00000000..d9690ec3
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.asn1.oiw;
+
+import org.bouncycastle.asn1.DERObjectIdentifier;
+
+public interface OIWObjectIdentifiers
+{
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ static final DERObjectIdentifier md4WithRSA = new DERObjectIdentifier("1.3.14.3.2.2");
+ static final DERObjectIdentifier md5WithRSA = new DERObjectIdentifier("1.3.14.3.2.3");
+ static final DERObjectIdentifier md4WithRSAEncryption = new DERObjectIdentifier("1.3.14.3.2.4");
+
+ static final DERObjectIdentifier desECB = new DERObjectIdentifier("1.3.14.3.2.6");
+ static final DERObjectIdentifier desCBC = new DERObjectIdentifier("1.3.14.3.2.7");
+ static final DERObjectIdentifier desOFB = new DERObjectIdentifier("1.3.14.3.2.8");
+ static final DERObjectIdentifier desCFB = new DERObjectIdentifier("1.3.14.3.2.9");
+
+ static final DERObjectIdentifier desEDE = new DERObjectIdentifier("1.3.14.3.2.17");
+
+ static final DERObjectIdentifier idSHA1 = new DERObjectIdentifier("1.3.14.3.2.26");
+
+ static final DERObjectIdentifier dsaWithSHA1 = new DERObjectIdentifier("1.3.14.3.2.27");
+
+ static final DERObjectIdentifier sha1WithRSA = new DERObjectIdentifier("1.3.14.3.2.29");
+
+ // ElGamal Algorithm OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ //
+ static final DERObjectIdentifier elGamalAlgorithm = new DERObjectIdentifier("1.3.14.7.2.1.1");
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/Attribute.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/Attribute.java
new file mode 100644
index 00000000..0c543926
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/Attribute.java
@@ -0,0 +1,82 @@
+package org.bouncycastle.asn1.pkcs;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Encodable
+{
+ private DERObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new Attribute((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public Attribute(
+ ASN1Sequence seq)
+ {
+ attrType = (DERObjectIdentifier)seq.getObjectAt(0);
+ attrValues = (ASN1Set)seq.getObjectAt(1);
+ }
+
+ public Attribute(
+ DERObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public DERObjectIdentifier getAttrType()
+ {
+ return attrType;
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * This routine is written to output PKCS1 version 2.1, private keys.
+ */
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DERInteger(version)); // version
+ v.add(new DERInteger(getModulus()));
+ v.add(new DERInteger(getPublicExponent()));
+ v.add(new DERInteger(getPrivateExponent()));
+ v.add(new DERInteger(getPrime1()));
+ v.add(new DERInteger(getPrime2()));
+ v.add(new DERInteger(getExponent1()));
+ v.add(new DERInteger(getExponent2()));
+ v.add(new DERInteger(getCoefficient()));
+
+ if (otherPrimeInfos != null)
+ {
+ v.add(otherPrimeInfos);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SafeBag.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SafeBag.java
new file mode 100644
index 00000000..2808d92d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SafeBag.java
@@ -0,0 +1,78 @@
+package org.bouncycastle.asn1.pkcs;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+public class SafeBag
+ extends ASN1Encodable
+{
+ DERObjectIdentifier bagId;
+ DERObject bagValue;
+ ASN1Set bagAttributes;
+
+ public SafeBag(
+ DERObjectIdentifier oid,
+ DERObject obj)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = null;
+ }
+
+ public SafeBag(
+ DERObjectIdentifier oid,
+ DERObject obj,
+ ASN1Set bagAttributes)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = bagAttributes;
+ }
+
+ public SafeBag(
+ ASN1Sequence seq)
+ {
+ this.bagId = (DERObjectIdentifier)seq.getObjectAt(0);
+ this.bagValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ if (seq.size() == 3)
+ {
+ this.bagAttributes = (ASN1Set)seq.getObjectAt(2);
+ }
+ }
+
+ public DERObjectIdentifier getBagId()
+ {
+ return bagId;
+ }
+
+ public DERObject getBagValue()
+ {
+ return bagValue;
+ }
+
+ public ASN1Set getBagAttributes()
+ {
+ return bagAttributes;
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(bagId);
+ v.add(new DERTaggedObject(0, bagValue));
+
+ if (bagAttributes != null)
+ {
+ v.add(bagAttributes);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SignedData.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SignedData.java
new file mode 100644
index 00000000..1ac0c05e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/SignedData.java
@@ -0,0 +1,167 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * a PKCS#7 signed data object.
+ */
+@SuppressWarnings("unchecked")
+public class SignedData
+ extends ASN1Encodable
+ implements PKCSObjectIdentifiers
+{
+ private DERInteger version;
+ private ASN1Set digestAlgorithms;
+ private ContentInfo contentInfo;
+ private ASN1Set certificates;
+ private ASN1Set crls;
+ private ASN1Set signerInfos;
+
+ public static SignedData getInstance(
+ Object o)
+ {
+ if (o instanceof SignedData)
+ {
+ return (SignedData)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SignedData((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o);
+ }
+
+ public SignedData(
+ DERInteger _version,
+ ASN1Set _digestAlgorithms,
+ ContentInfo _contentInfo,
+ ASN1Set _certificates,
+ ASN1Set _crls,
+ ASN1Set _signerInfos)
+ {
+ version = _version;
+ digestAlgorithms = _digestAlgorithms;
+ contentInfo = _contentInfo;
+ certificates = _certificates;
+ crls = _crls;
+ signerInfos = _signerInfos;
+ }
+
+ public SignedData(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (DERInteger)e.nextElement();
+ digestAlgorithms = ((ASN1Set)e.nextElement());
+ contentInfo = ContentInfo.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ DERObject o = (DERObject)e.nextElement();
+
+ //
+ // an interesting feature of SignedData is that there appear to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o instanceof DERTaggedObject)
+ {
+ DERTaggedObject tagged = (DERTaggedObject)o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ certificates = ASN1Set.getInstance(tagged, false);
+ break;
+ case 1:
+ crls = ASN1Set.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else
+ {
+ signerInfos = (ASN1Set)o;
+ }
+ }
+ }
+
+ public DERInteger getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Set getDigestAlgorithms()
+ {
+ return digestAlgorithms;
+ }
+
+ public ContentInfo getContentInfo()
+ {
+ return contentInfo;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certificates;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ public ASN1Set getSignerInfos()
+ {
+ return signerInfos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Note: in the case where the underlying cipher is either a CFB cipher or an
+ * OFB one the last block may not be a multiple of the block size.
+ */
+public class BufferedBlockCipher
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected boolean forEncryption;
+ protected BlockCipher cipher;
+
+ protected boolean partialBlockOkay;
+ protected boolean pgpCFB;
+
+ /**
+ * constructor for subclasses
+ */
+ protected BufferedBlockCipher()
+ {
+ }
+
+ /**
+ * Create a buffered block cipher without padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public BufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+
+ //
+ // check if we can handle partial blocks on doFinal.
+ //
+ String name = cipher.getAlgorithmName();
+ int idx = name.indexOf('/') + 1;
+
+ pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
+
+ if (pgpCFB)
+ {
+ partialBlockOkay = true;
+ }
+ else
+ {
+ partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ }
+ }
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ cipher.init(forEncryption, params);
+ }
+
+ /**
+ * return the blocksize for the underlying cipher.
+ *
+ * @return the blocksize for the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver;
+
+ if (pgpCFB)
+ {
+ leftOver = total % buf.length - (cipher.getBlockSize() + 2);
+ }
+ else
+ {
+ leftOver = total % buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of 'length' bytes.
+ *
+ * @param length the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with 'length' bytes of input.
+ */
+ public int getOutputSize(
+ int length)
+ {
+ // Note: Can assume partialBlockOkay is true for purposes of this calculation
+ return length + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ if (bufOff == buf.length)
+ {
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output, or the input is not block size aligned and should be.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ * @exception DataLengthException if the input is not block size
+ * aligned.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int resultLen = 0;
+
+ if (outOff + bufOff > out.length)
+ {
+ throw new DataLengthException("output buffer too short for doFinal()");
+ }
+
+ if (bufOff != 0 && partialBlockOkay)
+ {
+ cipher.processBlock(buf, 0, buf, 0);
+ resultLen = bufOff;
+ bufOff = 0;
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+ else if (bufOff != 0)
+ {
+ throw new DataLengthException("data not block size aligned");
+ }
+
+ reset();
+
+ return resultLen;
+ }
+
+ /**
+ * Reset the buffer and cipher. After resetting the object is in the same
+ * state as it was after the last init (if there was one).
+ */
+ public void reset()
+ {
+ //
+ // clean the buffer.
+ //
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ //
+ // reset the underlying cipher.
+ //
+ cipher.reset();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CipherParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CipherParameters.java
new file mode 100644
index 00000000..5be87304
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CipherParameters.java
@@ -0,0 +1,8 @@
+package org.bouncycastle.crypto;
+
+/**
+ * all parameter classes implement this.
+ */
+public interface CipherParameters
+{
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CryptoException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CryptoException.java
new file mode 100644
index 00000000..cafc4cfa
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/CryptoException.java
@@ -0,0 +1,27 @@
+package org.bouncycastle.crypto;
+
+/**
+ * the foundation class for the hard exceptions thrown by the crypto packages.
+ */
+@SuppressWarnings("serial")
+public class CryptoException
+ extends Exception
+{
+ /**
+ * base constructor.
+ */
+ public CryptoException()
+ {
+ }
+
+ /**
+ * create a CryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public CryptoException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/DataLengthException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/DataLengthException.java
new file mode 100644
index 00000000..29b37ae4
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/DataLengthException.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown if a buffer that is meant to have output
+ * copied into it turns out to be too short, or if we've been given
+ * insufficient input. In general this exception will get thrown rather
+ * than an ArrayOutOfBounds exception.
+ */
+@SuppressWarnings("serial")
+public class DataLengthException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public DataLengthException()
+ {
+ }
+
+ /**
+ * create a DataLengthException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public DataLengthException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Digest.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Digest.java
new file mode 100644
index 00000000..f44fad0d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Digest.java
@@ -0,0 +1,51 @@
+package org.bouncycastle.crypto;
+
+/**
+ * interface that a message digest conforms to.
+ */
+public interface Digest
+{
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize();
+
+ /**
+ * update the message digest with a single byte.
+ *
+ * @param in the input byte to be entered.
+ */
+ public void update(byte in);
+
+ /**
+ * update the message digest with a block of bytes.
+ *
+ * @param in the byte array containing the data.
+ * @param inOff the offset into the byte array where the data starts.
+ * @param len the length of the data.
+ */
+ public void update(byte[] in, int inOff, int len);
+
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff);
+
+ /**
+ * reset the digest back to it's initial state.
+ */
+ public void reset();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/ExtendedDigest.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/ExtendedDigest.java
new file mode 100644
index 00000000..c5e9e8b0
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/ExtendedDigest.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.crypto;
+
+public interface ExtendedDigest
+ extends Digest
+{
+ /**
+ * Return the size in bytes of the internal buffer the digest applies it's compression
+ * function to.
+ *
+ * @return byte length of the digests internal buffer.
+ */
+ public int getByteLength();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/InvalidCipherTextException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/InvalidCipherTextException.java
new file mode 100644
index 00000000..6d4b4141
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/InvalidCipherTextException.java
@@ -0,0 +1,28 @@
+package org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown whenever we find something we don't expect in a
+ * message.
+ */
+@SuppressWarnings("serial")
+public class InvalidCipherTextException
+ extends CryptoException
+{
+ /**
+ * base constructor.
+ */
+ public InvalidCipherTextException()
+ {
+ }
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public InvalidCipherTextException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Mac.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Mac.java
new file mode 100644
index 00000000..c00cd58c
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Mac.java
@@ -0,0 +1,71 @@
+package org.bouncycastle.crypto;
+
+
+/**
+ * The base interface for implementations of message authentication codes (MACs).
+ */
+public interface Mac
+{
+ /**
+ * Initialise the MAC.
+ *
+ * @param params the key and other data required by the MAC.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the MAC implements.
+ *
+ * @return the name of the algorithm the MAC implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this MAC (in bytes).
+ *
+ * @return the block size for this MAC in bytes.
+ */
+ public int getMacSize();
+
+ /**
+ * add a single byte to the mac for processing.
+ *
+ * @param in the byte to be processed.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public void update(byte in)
+ throws IllegalStateException;
+
+ /**
+ * @param in the array containing the input.
+ * @param inOff the index in the array the data begins at.
+ * @param len the length of the input starting at inOff.
+ * @exception IllegalStateException if the MAC is not initialised.
+ * @exception DataLengthException if there isn't enough data in in.
+ */
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Compute the final stage of the MAC writing the output to the out
+ * parameter.
+ *
+ * doFinal leaves the MAC in the same state it was after the last init.
+ *
+ * @param out the array the MAC is to be output to.
+ * @param outOff the offset into the out buffer the output is to start at.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the MAC. At the end of resetting the MAC should be in the
+ * in the same state it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/MaxBytesExceededException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/MaxBytesExceededException.java
new file mode 100644
index 00000000..5747f27c
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/MaxBytesExceededException.java
@@ -0,0 +1,28 @@
+package org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown whenever a cipher requires a change of key, iv
+ * or similar after x amount of bytes enciphered
+ */
+@SuppressWarnings("serial")
+public class MaxBytesExceededException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public MaxBytesExceededException()
+ {
+ }
+
+ /**
+ * create an with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public MaxBytesExceededException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/PBEParametersGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/PBEParametersGenerator.java
new file mode 100644
index 00000000..82eaa5f6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/PBEParametersGenerator.java
@@ -0,0 +1,157 @@
+package org.bouncycastle.crypto;
+
+import org.bouncycastle.util.Strings;
+
+/**
+ * super class for all Password Based Encryption (PBE) parameter generator classes.
+ */
+public abstract class PBEParametersGenerator
+{
+ protected byte[] password;
+ protected byte[] salt;
+ protected int iterationCount;
+
+ /**
+ * base constructor.
+ */
+ protected PBEParametersGenerator()
+ {
+ }
+
+ /**
+ * initialise the PBE generator.
+ *
+ * @param password the password converted into bytes (see below).
+ * @param salt the salt to be mixed with the password.
+ * @param iterationCount the number of iterations the "mixing" function
+ * is to be applied for.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.password = password;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * return the password byte array.
+ *
+ * @return the password byte array.
+ */
+ public byte[] getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * return the salt byte array.
+ *
+ * @return the salt byte array.
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ /**
+ * return the iteration count.
+ *
+ * @return the iteration count.
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ * generate derived parameters for a key of length keySize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize);
+
+ /**
+ * generate derived parameters for a key of length keySize, and
+ * an initialisation vector (IV) of length ivSize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @param ivSize the length, in bits, of the iv required.
+ * @return a parameters object representing a key and an IV.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize);
+
+ /**
+ * generate derived parameters for a key of length keySize, specifically
+ * for use with a MAC.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedMacParameters(int keySize);
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (ascii, no padding)
+ *
+ * @param password a character array reqpresenting the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToBytes(
+ char[] password)
+ {
+ byte[] bytes = new byte[password.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (UTF-8, no padding)
+ *
+ * @param password a character array reqpresenting the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToUTF8Bytes(
+ char[] password)
+ {
+ return Strings.toUTF8ByteArray(password);
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS12 (unicode, big endian, 2 zero pad bytes at the end).
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS12PasswordToBytes(
+ char[] password)
+ {
+ if (password.length > 0)
+ {
+ // +1 for extra 2 pad bytes.
+ byte[] bytes = new byte[(password.length + 1) * 2];
+
+ for (int i = 0; i != password.length; i ++)
+ {
+ bytes[i * 2] = (byte)(password[i] >>> 8);
+ bytes[i * 2 + 1] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/RuntimeCryptoException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/RuntimeCryptoException.java
new file mode 100644
index 00000000..8e782dee
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/RuntimeCryptoException.java
@@ -0,0 +1,27 @@
+package org.bouncycastle.crypto;
+
+/**
+ * the foundation class for the exceptions thrown by the crypto packages.
+ */
+@SuppressWarnings("serial")
+public class RuntimeCryptoException
+ extends RuntimeException
+{
+ /**
+ * base constructor.
+ */
+ public RuntimeCryptoException()
+ {
+ }
+
+ /**
+ * create a RuntimeCryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public RuntimeCryptoException(
+ String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamBlockCipher.java
new file mode 100644
index 00000000..8fdd2324
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamBlockCipher.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.crypto;
+
+/**
+ * a wrapper for block ciphers with a single byte block size, so that they
+ * can be treated like stream ciphers.
+ */
+public class StreamBlockCipher
+ implements StreamCipher
+{
+ private 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)
+ {
+ if (cipher.getBlockSize() != 1)
+ {
+ throw new IllegalArgumentException("block cipher block size != 1.");
+ }
+
+ this.cipher = cipher;
+ }
+
+ /**
+ * initialise the underlying cipher.
+ *
+ * @param forEncryption true if we are setting up for encryption, false otherwise.
+ * @param params the necessary parameters for the underlying cipher to be initialised.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ cipher.init(forEncryption, params);
+ }
+
+ /**
+ * return the name of the algorithm we are wrapping.
+ *
+ * @return the name of the algorithm we are wrapping.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ /**
+ * 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)
+ throws DataLengthException
+ {
+ if (outOff + len > out.length)
+ {
+ throw new DataLengthException("output buffer too small in processBytes()");
+ }
+
+ for (int i = 0; i != len; i++)
+ {
+ cipher.processBlock(in, inOff + i, out, outOff + i);
+ }
+ }
+
+ /**
+ * 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();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamCipher.java
new file mode 100644
index 00000000..2a55d4f6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/StreamCipher.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.crypto;
+
+/**
+ * the interface stream ciphers conform to.
+ */
+public interface StreamCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * 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);
+
+ /**
+ * 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 starts at.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * reset the cipher. This leaves it in the same state
+ * it was at after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Wrapper.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Wrapper.java
new file mode 100644
index 00000000..3956a6fc
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/Wrapper.java
@@ -0,0 +1,18 @@
+package org.bouncycastle.crypto;
+
+public interface Wrapper
+{
+ public void init(boolean forWrapping, CipherParameters param);
+
+ /**
+ * Return the name of the algorithm the wrapper implements.
+ *
+ * @return the name of the algorithm the wrapper implements.
+ */
+ public String getAlgorithmName();
+
+ public byte[] wrap(byte[] in, int inOff, int inLen);
+
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/GeneralDigest.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/GeneralDigest.java
new file mode 100644
index 00000000..f2c99674
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/GeneralDigest.java
@@ -0,0 +1,135 @@
+package org.bouncycastle.crypto.digests;
+
+import org.bouncycastle.crypto.ExtendedDigest;
+
+/**
+ * base implementation of MD4 family style digest as outlined in
+ * "Handbook of Applied Cryptography", pages 344 - 347.
+ */
+public abstract class GeneralDigest
+ implements ExtendedDigest
+{
+ 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];
+ 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;
+ }
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/MD2Digest.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/MD2Digest.java
new file mode 100644
index 00000000..0edafbc1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/MD2Digest.java
@@ -0,0 +1,237 @@
+package org.bouncycastle.crypto.digests;
+
+import org.bouncycastle.crypto.*;
+/**
+ * implementation of MD2
+ * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+ */
+public class MD2Digest
+ implements ExtendedDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ /* X buffer */
+ private byte[] X = new byte[48];
+ private int xOff;
+ /* M buffer */
+ private byte[] M = new byte[16];
+ private int mOff;
+ /* check sum */
+ private byte[] C = new byte[16];
+ private int COff;
+
+ public MD2Digest()
+ {
+ reset();
+ }
+ public MD2Digest(MD2Digest t)
+ {
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ System.arraycopy(t.M, 0, M, 0, t.M.length);
+ mOff = t.mOff;
+ System.arraycopy(t.C, 0, C, 0, t.C.length);
+ COff = t.COff;
+ }
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName()
+ {
+ return "MD2";
+ }
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff)
+ {
+ // add padding
+ byte paddingByte = (byte)(M.length-mOff);
+ for (int i=mOff;i
+ *
+ * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+ * iteration count of 1.
+ *
+ */
+public class OpenSSLPBEParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest = new MD5Digest();
+
+ /**
+ * Construct a OpenSSL Parameters generator.
+ */
+ public OpenSSLPBEParametersGenerator()
+ {
+ }
+
+ /**
+ * Initialise - note the iteration count for this algorithm is fixed at 1.
+ *
+ * @param password password to use.
+ * @param salt salt to use.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt)
+ {
+ super.init(password, salt, 1);
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey(
+ int bytesNeeded)
+ {
+ byte[] buf = new byte[digest.getDigestSize()];
+ byte[] key = new byte[bytesNeeded];
+ int offset = 0;
+
+ for (;;)
+ {
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(buf, 0);
+
+ int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
+ System.arraycopy(buf, 0, key, offset, len);
+ offset += len;
+
+ // check if we need any more
+ bytesNeeded -= len;
+ if (bytesNeeded == 0)
+ {
+ break;
+ }
+
+ // do another round
+ digest.reset();
+ digest.update(buf, 0, buf.length);
+ }
+
+ return key;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
new file mode 100644
index 00000000..bf2f3689
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
@@ -0,0 +1,221 @@
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS12 Page
+ */
+public class PKCS12ParametersGenerator
+ extends PBEParametersGenerator
+{
+ public static final int KEY_MATERIAL = 1;
+ public static final int IV_MATERIAL = 2;
+ public static final int MAC_MATERIAL = 3;
+
+ private Digest digest;
+
+ private int u;
+ private int v;
+
+ /**
+ * Construct a PKCS 12 Parameters generator. This constructor will
+ * accept any digest which also implements ExtendedDigest.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ * @exception IllegalArgumentException if an unknown digest is passed in.
+ */
+ public PKCS12ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ if (digest instanceof ExtendedDigest)
+ {
+ u = digest.getDigestSize();
+ v = ((ExtendedDigest)digest).getByteLength();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported");
+ }
+ }
+
+ /**
+ * add a + b + 1, returning the result in a. The a value is treated
+ * as a BigInteger of length (b.length * 8) bits. The result is
+ * modulo 2^b.length in case of overflow.
+ */
+ private void adjust(
+ byte[] a,
+ int aOff,
+ byte[] b)
+ {
+ int x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
+
+ a[aOff + b.length - 1] = (byte)x;
+ x >>>= 8;
+
+ for (int i = b.length - 2; i >= 0; i--)
+ {
+ x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
+ a[aOff + i] = (byte)x;
+ x >>>= 8;
+ }
+ }
+
+ /**
+ * generation of a derived key ala PKCS12 V1.0.
+ */
+ private byte[] generateDerivedKey(
+ int idByte,
+ int n)
+ {
+ byte[] D = new byte[v];
+ byte[] dKey = new byte[n];
+
+ for (int i = 0; i != D.length; i++)
+ {
+ D[i] = (byte)idByte;
+ }
+
+ byte[] S;
+
+ if ((salt != null) && (salt.length != 0))
+ {
+ S = new byte[v * ((salt.length + v - 1) / v)];
+
+ for (int i = 0; i != S.length; i++)
+ {
+ S[i] = salt[i % salt.length];
+ }
+ }
+ else
+ {
+ S = new byte[0];
+ }
+
+ byte[] P;
+
+ if ((password != null) && (password.length != 0))
+ {
+ P = new byte[v * ((password.length + v - 1) / v)];
+
+ for (int i = 0; i != P.length; i++)
+ {
+ P[i] = password[i % password.length];
+ }
+ }
+ else
+ {
+ P = new byte[0];
+ }
+
+ byte[] I = new byte[S.length + P.length];
+
+ System.arraycopy(S, 0, I, 0, S.length);
+ System.arraycopy(P, 0, I, S.length, P.length);
+
+ byte[] B = new byte[v];
+ int c = (n + u - 1) / u;
+
+ for (int i = 1; i <= c; i++)
+ {
+ byte[] A = new byte[u];
+
+ digest.update(D, 0, D.length);
+ digest.update(I, 0, I.length);
+ digest.doFinal(A, 0);
+ for (int j = 1; j != iterationCount; j++)
+ {
+ digest.update(A, 0, A.length);
+ digest.doFinal(A, 0);
+ }
+
+ for (int j = 0; j != B.length; j++)
+ {
+ B[j] = A[j % A.length];
+ }
+
+ for (int j = 0; j != I.length / v; j++)
+ {
+ adjust(I, j * v, B);
+ }
+
+ if (i == c)
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
+ }
+ else
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, A.length);
+ }
+ }
+
+ return dKey;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ byte[] iv = generateDerivedKey(IV_MATERIAL, ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(MAC_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
new file mode 100644
index 00000000..1c62eccc
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
@@ -0,0 +1,119 @@
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1.
+ * Note this generator is limited to the size of the hash produced by the
+ * digest used to drive it.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS5 Page
+ */
+public class PKCS5S1ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest;
+
+ /**
+ * Construct a PKCS 5 Scheme 1 Parameters generator.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public PKCS5S1ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey()
+ {
+ byte[] digestBytes = new byte[digest.getDigestSize()];
+
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(digestBytes, 0);
+ for (int i = 1; i < iterationCount; i++)
+ {
+ digest.update(digestBytes, 0, digestBytes.length);
+ digest.doFinal(digestBytes, 0);
+ }
+
+ return digestBytes;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ if (keySize > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + keySize + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ if ((keySize + ivSize) > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + (keySize + ivSize) + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
new file mode 100644
index 00000000..9b4972d5
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
@@ -0,0 +1,151 @@
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
+ * This generator uses a SHA-1 HMac as the calculation function.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS5 Page
+ */
+public class PKCS5S2ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Mac hMac = new HMac(new SHA1Digest());
+
+ /**
+ * construct a PKCS5 Scheme 2 Parameters generator.
+ */
+ public PKCS5S2ParametersGenerator()
+ {
+ }
+
+ private void F(
+ byte[] P,
+ byte[] S,
+ int c,
+ byte[] iBuf,
+ byte[] out,
+ int outOff)
+ {
+ byte[] state = new byte[hMac.getMacSize()];
+ CipherParameters param = new KeyParameter(P);
+
+ hMac.init(param);
+
+ if (S != null)
+ {
+ hMac.update(S, 0, S.length);
+ }
+
+ hMac.update(iBuf, 0, iBuf.length);
+
+ hMac.doFinal(state, 0);
+
+ System.arraycopy(state, 0, out, outOff, state.length);
+
+ if (c == 0)
+ {
+ throw new IllegalArgumentException("iteration count must be at least 1.");
+ }
+
+ for (int count = 1; count < c; count++)
+ {
+ hMac.init(param);
+ hMac.update(state, 0, state.length);
+ hMac.doFinal(state, 0);
+
+ for (int j = 0; j != state.length; j++)
+ {
+ out[outOff + j] ^= state[j];
+ }
+ }
+ }
+
+ private void intToOctet(
+ byte[] buf,
+ int i)
+ {
+ buf[0] = (byte)(i >>> 24);
+ buf[1] = (byte)(i >>> 16);
+ buf[2] = (byte)(i >>> 8);
+ buf[3] = (byte)i;
+ }
+
+ private byte[] generateDerivedKey(
+ int dkLen)
+ {
+ int hLen = hMac.getMacSize();
+ int l = (dkLen + hLen - 1) / hLen;
+ byte[] iBuf = new byte[4];
+ byte[] out = new byte[l * hLen];
+
+ for (int i = 1; i <= l; i++)
+ {
+ intToOctet(iBuf, i);
+
+ F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen);
+ }
+
+ return out;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/macs/HMac.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/macs/HMac.java
new file mode 100644
index 00000000..7189426a
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/macs/HMac.java
@@ -0,0 +1,200 @@
+package org.bouncycastle.crypto.macs;
+
+import java.util.Hashtable;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.ExtendedDigest;
+import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * HMAC implementation based on RFC2104
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ */
+@SuppressWarnings("unchecked")
+public class HMac
+ implements Mac
+{
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ private Digest digest;
+ private int digestSize;
+ private int blockLength;
+
+ private byte[] inputPad;
+ private byte[] outputPad;
+
+ private static Hashtable blockLengths;
+
+ static
+ {
+ blockLengths = new Hashtable();
+
+ blockLengths.put("GOST3411", Integer.valueOf(32));
+
+ blockLengths.put("MD2", Integer.valueOf(16));
+ blockLengths.put("MD4", Integer.valueOf(64));
+ blockLengths.put("MD5", Integer.valueOf(64));
+
+ blockLengths.put("RIPEMD128", Integer.valueOf(64));
+ blockLengths.put("RIPEMD160", Integer.valueOf(64));
+
+ blockLengths.put("SHA-1", Integer.valueOf(64));
+ blockLengths.put("SHA-224", Integer.valueOf(64));
+ blockLengths.put("SHA-256", Integer.valueOf(64));
+ blockLengths.put("SHA-384", Integer.valueOf(128));
+ blockLengths.put("SHA-512", Integer.valueOf(128));
+
+ blockLengths.put("Tiger", Integer.valueOf(64));
+ blockLengths.put("Whirlpool", Integer.valueOf(64));
+ }
+
+ private static int getByteLength(
+ Digest digest)
+ {
+ if (digest instanceof ExtendedDigest)
+ {
+ return ((ExtendedDigest)digest).getByteLength();
+ }
+
+ Integer b = (Integer)blockLengths.get(digest.getAlgorithmName());
+
+ if (b == null)
+ {
+ throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName());
+ }
+
+ return b.intValue();
+ }
+
+ /**
+ * Base constructor for one of the standard digest algorithms that the
+ * byteLength of the algorithm is know for.
+ *
+ * @param digest the digest.
+ */
+ public HMac(
+ Digest digest)
+ {
+ this(digest, getByteLength(digest));
+ }
+
+ private HMac(
+ Digest digest,
+ int byteLength)
+ {
+ this.digest = digest;
+ digestSize = digest.getDigestSize();
+
+ this.blockLength = byteLength;
+
+ inputPad = new byte[blockLength];
+ outputPad = new byte[blockLength];
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/HMAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ digest.reset();
+
+ byte[] key = ((KeyParameter)params).getKey();
+
+ if (key.length > blockLength)
+ {
+ digest.update(key, 0, key.length);
+ digest.doFinal(inputPad, 0);
+ for (int i = digestSize; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(key, 0, inputPad, 0, key.length);
+ for (int i = key.length; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+
+ outputPad = new byte[inputPad.length];
+ System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
+
+ for (int i = 0; i < inputPad.length; i++)
+ {
+ inputPad[i] ^= IPAD;
+ }
+
+ for (int i = 0; i < outputPad.length; i++)
+ {
+ outputPad[i] ^= OPAD;
+ }
+
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ public int getMacSize()
+ {
+ return digestSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ byte[] tmp = new byte[digestSize];
+ digest.doFinal(tmp, 0);
+
+ digest.update(outputPad, 0, outputPad.length);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * reset the underlying digest.
+ */
+ digest.reset();
+
+ /*
+ * reinitialize the digest.
+ */
+ digest.update(inputPad, 0, inputPad.length);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/AEADBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/AEADBlockCipher.java
new file mode 100644
index 00000000..3c3bf341
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/AEADBlockCipher.java
@@ -0,0 +1,108 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data.
+ * @see org.bouncycastle.crypto.params.AEADParameters
+ */
+public interface AEADBlockCipher
+{
+ /**
+ * initialise the underlying cipher. Parameter can either be an AEADParameters or a ParametersWithIV object.
+ *
+ * @param forEncryption true if we are setting up for encryption, false otherwise.
+ * @param params the necessary parameters for the underlying cipher to be initialised.
+ * @exception IllegalArgumentException if the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm.
+ *
+ * @return the algorithm name.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher();
+
+ /**
+ * encrypt/decrypt a single byte.
+ *
+ * @param in the byte to be processed.
+ * @param out the output buffer the processed byte goes into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * 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 starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * Finish the operation either appending or verifying the MAC at the end of the data.
+ *
+ * @param out space for any resulting output data.
+ * @param outOff offset into out to start copying the data at.
+ * @return number of bytes written into out.
+ * @throws IllegalStateException if the cipher is in an inappropriate state.
+ * @throws org.bouncycastle.crypto.InvalidCipherTextException if the MAC fails to match.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException;
+
+ /**
+ * Return the value of the MAC associated with the last stream processed.
+ *
+ * @return MAC for plaintext data.
+ */
+ public byte[] getMac();
+
+ /**
+ * return the size of the output buffer required for a processBytes
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(int len);
+
+ /**
+ * return the size of the output buffer required for a processBytes plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(int len);
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java
new file mode 100644
index 00000000..f75c5463
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java
@@ -0,0 +1,235 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
+
+/**
+ * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+ */
+public class CBCBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] cbcV;
+ private byte[] cbcNextV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of chaining.
+ */
+ public CBCBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.blockSize = cipher.getBlockSize();
+
+ this.IV = new byte[blockSize];
+ this.cbcV = new byte[blockSize];
+ this.cbcNextV = new byte[blockSize];
+ }
+
+ /**
+ * 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.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length != blockSize)
+ {
+ throw new IllegalArgumentException("initialisation vector must be the same length as block size");
+ }
+
+ System.arraycopy(iv, 0, IV, 0, iv.length);
+
+ reset();
+
+ cipher.init(encrypting, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(encrypting, params);
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CBC".
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CBC";
+ }
+
+ /**
+ * return the block size of the underlying cipher.
+ *
+ * @return the block size of the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cbcV, 0, IV.length);
+ Arrays.fill(cbcNextV, (byte)0);
+
+ cipher.reset();
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ /*
+ * XOR the cbcV and the input,
+ * then encrypt the cbcV
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ cbcV[i] ^= in[inOff + i];
+ }
+
+ int length = cipher.processBlock(cbcV, 0, out, outOff);
+
+ /*
+ * copy ciphertext to cbcV
+ */
+ System.arraycopy(out, outOff, cbcV, 0, cbcV.length);
+
+ return length;
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the decrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ System.arraycopy(in, inOff, cbcNextV, 0, blockSize);
+
+ int length = cipher.processBlock(in, inOff, out, outOff);
+
+ /*
+ * XOR the cbcV and the output
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] ^= cbcV[i];
+ }
+
+ /*
+ * swap the back up buffer into next position
+ */
+ byte[] tmp;
+
+ tmp = cbcV;
+ cbcV = cbcNextV;
+ cbcNextV = tmp;
+
+ return length;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java
new file mode 100644
index 00000000..0de04502
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -0,0 +1,250 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+ */
+public class CFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] cfbV;
+ private byte[] cfbOutV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param bitBlockSize the block size in bits (note: a multiple of 8)
+ */
+ public CFBBlockCipher(
+ BlockCipher cipher,
+ int bitBlockSize)
+ {
+ 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;
+ }
+
+ /**
+ * 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.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ 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);
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ 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]);
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cfbV, 0, IV.length);
+
+ cipher.reset();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java
new file mode 100644
index 00000000..b8e5b610
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -0,0 +1,265 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+ * be used to produce cipher text which is the same length as the plain text.
+ */
+public class CTSBlockCipher
+ extends BufferedBlockCipher
+{
+ private int blockSize;
+
+ /**
+ * Create a buffered block cipher that uses Cipher Text Stealing
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public CTSBlockCipher(
+ BlockCipher cipher)
+ {
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ {
+ throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
+ }
+
+ this.cipher = cipher;
+
+ blockSize = cipher.getBlockSize();
+
+ buf = new byte[blockSize * 2];
+ bufOff = 0;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ return len + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, blockSize);
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if cipher text decrypts wrongly (in
+ * case the exception will never get thrown).
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ if (bufOff + outOff > out.length)
+ {
+ throw new DataLengthException("output buffer to small in doFinal");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int len = bufOff - blockSize;
+ byte[] block = new byte[blockSize];
+
+ if (forEncryption)
+ {
+ cipher.processBlock(buf, 0, block, 0);
+
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
+ }
+ else
+ {
+ byte[] lastBlock = new byte[blockSize];
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
+ }
+
+ int offset = bufOff;
+
+ reset();
+
+ return offset;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java
new file mode 100644
index 00000000..f209b9fc
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java
@@ -0,0 +1,179 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+ */
+public class OFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+
+ private final int blockSize;
+ private final BlockCipher cipher;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param blockSize the block size in bits (note: a multiple of 8)
+ */
+ public OFBBlockCipher(
+ BlockCipher cipher,
+ int blockSize)
+ {
+ this.cipher = cipher;
+ this.blockSize = blockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.ofbV = new byte[cipher.getBlockSize()];
+ 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.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting, //ignored by this OFB mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/OFB"
+ * and the block size in bits
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
+ }
+
+
+ /**
+ * return the block size we are operating at (in bytes).
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ 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);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the feedback vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, ofbV, 0, IV.length);
+
+ cipher.reset();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/paddings/BlockCipherPadding.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
new file mode 100644
index 00000000..7c4f0aee
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
@@ -0,0 +1,48 @@
+package org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * Block cipher padders are expected to conform to this interface
+ */
+public interface BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random the source of randomness for the padding, if required.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getPaddingName();
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ *
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text. The reason
+ * for this is that some modes such as "trailing bit compliment"
+ * base the padding on the last byte of plain text.
+ *
+ * See "Applied
+ * Cryptography" by Bruce Schneier for more information.
+ *
+ * @return true if the given DES key material is weak or semi-weak,
+ * false otherwise.
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ if (key.length - offset < DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("key material too short.");
+ }
+
+ nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+ {
+ for (int j = 0; j < DES_KEY_LENGTH; j++)
+ {
+ if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
+ {
+ continue nextkey;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * DES Keys use the LSB as the odd parity bit. This can
+ * be used to check for corrupt keys.
+ *
+ * @param bytes the byte array to set the parity on.
+ */
+ public static void setOddParity(
+ byte[] bytes)
+ {
+ for (int i = 0; i < bytes.length; i++)
+ {
+ int b = bytes[i];
+ bytes[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHKeyParameters.java
new file mode 100644
index 00000000..e686f357
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHKeyParameters.java
@@ -0,0 +1,54 @@
+package org.bouncycastle.crypto.params;
+
+
+public class DHKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DHParameters params;
+
+ protected DHKeyParameters(
+ boolean isPrivate,
+ DHParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DHParameters getParameters()
+ {
+ return params;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHKeyParameters))
+ {
+ return false;
+ }
+
+ DHKeyParameters dhKey = (DHKeyParameters)obj;
+
+ if (params == null)
+ {
+ return dhKey.getParameters() == null;
+ }
+ else
+ {
+ return params.equals(dhKey.getParameters());
+ }
+ }
+
+ public int hashCode()
+ {
+ int code = isPrivate() ? 0 : 1;
+
+ if (params != null)
+ {
+ code ^= params.hashCode();
+ }
+
+ return code;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHParameters.java
new file mode 100644
index 00000000..95352cee
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHParameters.java
@@ -0,0 +1,188 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.CipherParameters;
+
+import java.math.BigInteger;
+
+public class DHParameters
+ implements CipherParameters
+{
+ private static final int DEFAULT_MINIMUM_LENGTH = 160;
+
+ // not final due to compiler bug in "simpler" JDKs
+ private BigInteger g;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger j;
+ private int m;
+ private int l;
+ private DHValidationParameters validation;
+
+ private static int getDefaultMParam(
+ int lParam)
+ {
+ if (lParam == 0)
+ {
+ return DEFAULT_MINIMUM_LENGTH;
+ }
+
+ return lParam < DEFAULT_MINIMUM_LENGTH ? lParam : DEFAULT_MINIMUM_LENGTH;
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g)
+ {
+ this(p, g, null, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q)
+ {
+ this(p, g, q, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int l)
+ {
+ this(p, g, q, getDefaultMParam(l), l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l)
+ {
+ this(p, g, q, m, l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ if (l != 0)
+ {
+ if (l >= p.bitLength())
+ {
+ throw new IllegalArgumentException("when l value specified, it must be less than bitlength(p)");
+ }
+ if (l < m)
+ {
+ throw new IllegalArgumentException("when l value specified, it may not be less than m value");
+ }
+ }
+
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.m = m;
+ this.l = l;
+ this.j = j;
+ this.validation = validation;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ /**
+ * Return the subgroup factor J.
+ *
+ * @return subgroup factor
+ */
+ public BigInteger getJ()
+ {
+ return j;
+ }
+
+ /**
+ * Return the minimum length of the private value.
+ *
+ * @return the minimum length of the private value in bits.
+ */
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * Return the private value length in bits - if set, zero otherwise
+ *
+ * @return the private value length in bits, zero otherwise.
+ */
+ public int getL()
+ {
+ return l;
+ }
+
+ public DHValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHParameters))
+ {
+ return false;
+ }
+
+ DHParameters pm = (DHParameters)obj;
+
+ if (this.getQ() != null)
+ {
+ if (!this.getQ().equals(pm.getQ()))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (pm.getQ() != null)
+ {
+ return false;
+ }
+ }
+
+ return pm.getP().equals(p) && pm.getG().equals(g);
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
new file mode 100644
index 00000000..ee1b34f9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DHPrivateKeyParameters
+ extends DHKeyParameters
+{
+ private BigInteger x;
+
+ public DHPrivateKeyParameters(
+ BigInteger x,
+ DHParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public int hashCode()
+ {
+ return x.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHPrivateKeyParameters))
+ {
+ return false;
+ }
+
+ DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj;
+
+ return other.getX().equals(this.x) && super.equals(obj);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHValidationParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHValidationParameters.java
new file mode 100644
index 00000000..b22f7a03
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DHValidationParameters.java
@@ -0,0 +1,50 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.util.Arrays;
+
+public class DHValidationParameters
+{
+ private byte[] seed;
+ private int counter;
+
+ public DHValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DHValidationParameters))
+ {
+ return false;
+ }
+
+ DHValidationParameters other = (DHValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAKeyParameters.java
new file mode 100644
index 00000000..11bb9d97
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAKeyParameters.java
@@ -0,0 +1,21 @@
+package org.bouncycastle.crypto.params;
+
+public class DSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DSAParameters params;
+
+ public DSAKeyParameters(
+ boolean isPrivate,
+ DSAParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DSAParameters getParameters()
+ {
+ return params;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAParameters.java
new file mode 100644
index 00000000..7f76d117
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAParameters.java
@@ -0,0 +1,74 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.CipherParameters;
+
+public class DSAParameters
+ implements CipherParameters
+{
+ private BigInteger g;
+ private BigInteger q;
+ private BigInteger p;
+ private DSAValidationParameters validation;
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ }
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ DSAValidationParameters params)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.validation = params;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public DSAValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DSAParameters))
+ {
+ return false;
+ }
+
+ DSAParameters pm = (DSAParameters)obj;
+
+ return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getQ().hashCode() ^ getG().hashCode();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
new file mode 100644
index 00000000..3bef3f40
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
@@ -0,0 +1,23 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DSAPrivateKeyParameters
+ extends DSAKeyParameters
+{
+ private BigInteger x;
+
+ public DSAPrivateKeyParameters(
+ BigInteger x,
+ DSAParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAValidationParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAValidationParameters.java
new file mode 100644
index 00000000..1cc4b93e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/DSAValidationParameters.java
@@ -0,0 +1,50 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.util.Arrays;
+
+public class DSAValidationParameters
+{
+ private byte[] seed;
+ private int counter;
+
+ public DSAValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DSAValidationParameters))
+ {
+ return false;
+ }
+
+ DSAValidationParameters other = (DSAValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/KeyParameter.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/KeyParameter.java
new file mode 100644
index 00000000..5c4fe0e0
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/KeyParameter.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.CipherParameters;
+
+public class KeyParameter
+ implements CipherParameters
+{
+ private byte[] key;
+
+ public KeyParameter(
+ byte[] key)
+ {
+ this(key, 0, key.length);
+ }
+
+ public KeyParameter(
+ byte[] key,
+ int keyOff,
+ int keyLen)
+ {
+ this.key = new byte[keyLen];
+
+ System.arraycopy(key, keyOff, this.key, 0, keyLen);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithIV.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithIV.java
new file mode 100644
index 00000000..4a1e6e9a
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithIV.java
@@ -0,0 +1,39 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.CipherParameters;
+
+public class ParametersWithIV
+ implements CipherParameters
+{
+ private byte[] iv;
+ private CipherParameters parameters;
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv)
+ {
+ this(parameters, iv, 0, iv.length);
+ }
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv,
+ int ivOff,
+ int ivLen)
+ {
+ this.iv = new byte[ivLen];
+ this.parameters = parameters;
+
+ System.arraycopy(iv, ivOff, this.iv, 0, ivLen);
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithRandom.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithRandom.java
new file mode 100644
index 00000000..a7b18e51
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/ParametersWithRandom.java
@@ -0,0 +1,36 @@
+package org.bouncycastle.crypto.params;
+
+import org.bouncycastle.crypto.CipherParameters;
+
+import java.security.SecureRandom;
+
+public class ParametersWithRandom
+ implements CipherParameters
+{
+ private SecureRandom random;
+ private CipherParameters parameters;
+
+ public ParametersWithRandom(
+ CipherParameters parameters,
+ SecureRandom random)
+ {
+ this.random = random;
+ this.parameters = parameters;
+ }
+
+ public ParametersWithRandom(
+ CipherParameters parameters)
+ {
+ this(parameters, new SecureRandom());
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAKeyParameters.java
new file mode 100644
index 00000000..4a2d9354
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAKeyParameters.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private BigInteger modulus;
+ private BigInteger exponent;
+
+ public RSAKeyParameters(
+ boolean isPrivate,
+ BigInteger modulus,
+ BigInteger exponent)
+ {
+ super(isPrivate);
+
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
new file mode 100644
index 00000000..b61cb5c4
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
@@ -0,0 +1,67 @@
+package org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAPrivateCrtKeyParameters
+ extends RSAKeyParameters
+{
+ private BigInteger e;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger dP;
+ private BigInteger dQ;
+ private BigInteger qInv;
+
+ /**
+ *
+ */
+ public RSAPrivateCrtKeyParameters(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger p,
+ BigInteger q,
+ BigInteger dP,
+ BigInteger dQ,
+ BigInteger qInv)
+ {
+ super(true, modulus, privateExponent);
+
+ this.e = publicExponent;
+ this.p = p;
+ this.q = q;
+ this.dP = dP;
+ this.dQ = dQ;
+ this.qInv = qInv;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return e;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getDP()
+ {
+ return dP;
+ }
+
+ public BigInteger getDQ()
+ {
+ return dQ;
+ }
+
+ public BigInteger getQInv()
+ {
+ return qInv;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/util/Pack.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/util/Pack.java
new file mode 100644
index 00000000..12b59998
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/util/Pack.java
@@ -0,0 +1,34 @@
+package org.bouncycastle.crypto.util;
+
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void 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 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 longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/ConfigurableProvider.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/ConfigurableProvider.java
new file mode 100644
index 00000000..5aa2d9c6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/ConfigurableProvider.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.jce.interfaces;
+
+/**
+ * Implemented by the BC provider. This allows setting of hidden parameters,
+ * such as the ImplicitCA parameters from X.962, if used.
+ */
+public interface ConfigurableProvider
+{
+ static final String THREAD_LOCAL_EC_IMPLICITLY_CA = "threadLocalEcImplicitlyCa";
+ static final String EC_IMPLICITLY_CA = "ecImplicitlyCa";
+
+ void setParameter(String parameterName, Object parameter);
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java
new file mode 100644
index 00000000..25f2947e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java
@@ -0,0 +1,22 @@
+package org.bouncycastle.jce.interfaces;
+
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+
+/**
+ * allow us to set attributes on objects that can go into a PKCS12 store.
+ */
+@SuppressWarnings("unchecked")
+public interface PKCS12BagAttributeCarrier
+{
+ void setBagAttribute(
+ DERObjectIdentifier oid,
+ DEREncodable attribute);
+
+ DEREncodable getBagAttribute(
+ DERObjectIdentifier oid);
+
+ Enumeration getBagAttributeKeys();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEBlockCipher.java
new file mode 100644
index 00000000..73448fd1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEBlockCipher.java
@@ -0,0 +1,1405 @@
+package org.bouncycastle.jce.provider;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+/*
+import org.bouncycastle.crypto.engines.AESFastEngine;
+import org.bouncycastle.crypto.engines.BlowfishEngine;
+import org.bouncycastle.crypto.engines.CAST5Engine;
+import org.bouncycastle.crypto.engines.CAST6Engine;
+import org.bouncycastle.crypto.engines.DESEngine;
+import org.bouncycastle.crypto.engines.DESedeEngine;
+import org.bouncycastle.crypto.engines.GOST28147Engine;
+import org.bouncycastle.crypto.engines.RC2Engine;
+import org.bouncycastle.crypto.engines.RC532Engine;
+import org.bouncycastle.crypto.engines.RC564Engine;
+import org.bouncycastle.crypto.engines.RC6Engine;
+import org.bouncycastle.crypto.engines.RijndaelEngine;
+import org.bouncycastle.crypto.engines.SEEDEngine;
+import org.bouncycastle.crypto.engines.SerpentEngine;
+import org.bouncycastle.crypto.engines.SkipjackEngine;
+import org.bouncycastle.crypto.engines.TEAEngine;
+*/
+import org.bouncycastle.crypto.engines.TwofishEngine;
+//import org.bouncycastle.crypto.engines.XTEAEngine;
+//import org.bouncycastle.crypto.modes.AEADBlockCipher;
+import org.bouncycastle.crypto.modes.CBCBlockCipher;
+//import org.bouncycastle.crypto.modes.CCMBlockCipher;
+import org.bouncycastle.crypto.modes.CFBBlockCipher;
+import org.bouncycastle.crypto.modes.CTSBlockCipher;
+/*
+import org.bouncycastle.crypto.modes.EAXBlockCipher;
+import org.bouncycastle.crypto.modes.GCMBlockCipher;
+import org.bouncycastle.crypto.modes.GOFBBlockCipher;
+*/
+import org.bouncycastle.crypto.modes.OFBBlockCipher;
+/*
+import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher;
+import org.bouncycastle.crypto.modes.PGPCFBBlockCipher;
+import org.bouncycastle.crypto.modes.SICBlockCipher;
+import org.bouncycastle.crypto.paddings.BlockCipherPadding;
+import org.bouncycastle.crypto.paddings.ISO10126d2Padding;
+import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
+*/
+import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
+/*
+import org.bouncycastle.crypto.paddings.TBCPadding;
+import org.bouncycastle.crypto.paddings.X923Padding;
+import org.bouncycastle.crypto.paddings.ZeroBytePadding;
+*/
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+/*
+import org.bouncycastle.crypto.params.ParametersWithSBox;
+import org.bouncycastle.crypto.params.RC2Parameters;
+import org.bouncycastle.crypto.params.RC5Parameters;
+import org.bouncycastle.jce.spec.GOST28147ParameterSpec;
+*/
+import org.bouncycastle.util.Strings;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEParameterSpec;
+/*
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.RC5ParameterSpec;
+*/
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+@SuppressWarnings("unchecked")
+public class JCEBlockCipher extends WrapCipherSpi
+ implements PBE
+{
+ //
+ // specs we can handle.
+ //
+ private Class[] availableSpecs =
+ {
+ //RC2ParameterSpec.class,
+ //RC5ParameterSpec.class,
+ IvParameterSpec.class,
+ PBEParameterSpec.class,
+ //GOST28147ParameterSpec.class
+ };
+
+ private BlockCipher baseEngine;
+ private GenericBlockCipher cipher;
+ private ParametersWithIV ivParam;
+
+ private int ivLength = 0;
+
+ private boolean padded;
+
+ private PBEParameterSpec pbeSpec = null;
+ private String pbeAlgorithm = null;
+
+ private String modeName = null;
+
+ protected JCEBlockCipher(
+ BlockCipher engine)
+ {
+ baseEngine = engine;
+
+ cipher = new BufferedGenericBlockCipher(engine);
+ }
+
+ protected JCEBlockCipher(
+ BlockCipher engine,
+ int ivLength)
+ {
+ baseEngine = engine;
+
+ this.cipher = new BufferedGenericBlockCipher(engine);
+ this.ivLength = ivLength / 8;
+ }
+
+ protected JCEBlockCipher(
+ BufferedBlockCipher engine,
+ int ivLength)
+ {
+ baseEngine = engine.getUnderlyingCipher();
+
+ this.cipher = new BufferedGenericBlockCipher(engine);
+ this.ivLength = ivLength / 8;
+ }
+
+ protected int engineGetBlockSize()
+ {
+ return baseEngine.getBlockSize();
+ }
+
+ protected byte[] engineGetIV()
+ {
+ return (ivParam != null) ? ivParam.getIV() : null;
+ }
+
+ protected int engineGetKeySize(
+ Key key)
+ {
+ return key.getEncoded().length * 8;
+ }
+
+ protected int engineGetOutputSize(
+ int inputLen)
+ {
+ return cipher.getOutputSize(inputLen);
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ if (engineParams == null)
+ {
+ if (pbeSpec != null)
+ {
+ try
+ {
+ engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, "BC");
+ engineParams.init(pbeSpec);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ else if (ivParam != null)
+ {
+ String name = cipher.getUnderlyingCipher().getAlgorithmName();
+
+ if (name.indexOf('/') >= 0)
+ {
+ name = name.substring(0, name.indexOf('/'));
+ }
+
+ try
+ {
+ engineParams = AlgorithmParameters.getInstance(name, "BC");
+ engineParams.init(ivParam.getIV());
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ }
+
+ return engineParams;
+ }
+
+ protected void engineSetMode(
+ String mode)
+ throws NoSuchAlgorithmException
+ {
+ modeName = Strings.toUpperCase(mode);
+
+ if (modeName.equals("ECB"))
+ {
+ ivLength = 0;
+ cipher = new BufferedGenericBlockCipher(baseEngine);
+ }
+ else if (modeName.equals("CBC"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(
+ new CBCBlockCipher(baseEngine));
+ }
+ else if (modeName.startsWith("OFB"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ if (modeName.length() != 3)
+ {
+ int wordSize = Integer.parseInt(modeName.substring(3));
+
+ cipher = new BufferedGenericBlockCipher(
+ new OFBBlockCipher(baseEngine, wordSize));
+ }
+ else
+ {
+ cipher = new BufferedGenericBlockCipher(
+ new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
+ }
+ }
+ else if (modeName.startsWith("CFB"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ if (modeName.length() != 3)
+ {
+ int wordSize = Integer.parseInt(modeName.substring(3));
+
+ cipher = new BufferedGenericBlockCipher(
+ new CFBBlockCipher(baseEngine, wordSize));
+ }
+ else
+ {
+ cipher = new BufferedGenericBlockCipher(
+ new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize()));
+ }
+ }
+ /*
+ else if (modeName.startsWith("PGP"))
+ {
+ boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV");
+
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(
+ new PGPCFBBlockCipher(baseEngine, inlineIV));
+ }
+ else if (modeName.equalsIgnoreCase("OpenPGPCFB"))
+ {
+ ivLength = 0;
+ cipher = new BufferedGenericBlockCipher(
+ new OpenPGPCFBBlockCipher(baseEngine));
+ }
+ else if (modeName.startsWith("SIC"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ if (ivLength < 16)
+ {
+ throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
+ }
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new SICBlockCipher(baseEngine)));
+ }
+ else if (modeName.startsWith("CTR"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new SICBlockCipher(baseEngine)));
+ }
+ else if (modeName.startsWith("GOFB"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(
+ new GOFBBlockCipher(baseEngine)));
+ }
+ else if (modeName.startsWith("CTS"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine)));
+ }
+ else if (modeName.startsWith("CCM"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine));
+ }
+ else if (modeName.startsWith("EAX"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine));
+ }
+ else if (modeName.startsWith("GCM"))
+ {
+ ivLength = baseEngine.getBlockSize();
+ cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine));
+ }
+ */
+ else
+ {
+ throw new NoSuchAlgorithmException("can't support mode " + mode);
+ }
+ }
+
+ protected void engineSetPadding(
+ String padding)
+ throws NoSuchPaddingException
+ {
+ String paddingName = Strings.toUpperCase(padding);
+
+ if (paddingName.equals("NOPADDING"))
+ {
+ if (cipher.wrapOnNoPadding())
+ {
+ cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher()));
+ }
+ }
+ else if (paddingName.equals("WITHCTS"))
+ {
+ cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher()));
+ }
+ else
+ {
+ padded = true;
+
+ if (isAEADModeName(modeName))
+ {
+ throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes.");
+ }
+ else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher());
+ }
+ /*
+ else if (paddingName.equals("ZEROBYTEPADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding());
+ }
+ else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding());
+ }
+ else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding());
+ }
+ else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding());
+ }
+ else if (paddingName.equals("TBCPADDING"))
+ {
+ cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding());
+ }
+ */
+ else
+ {
+ throw new NoSuchPaddingException("Padding " + padding + " unknown.");
+ }
+ }
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+
+ this.pbeSpec = null;
+ this.pbeAlgorithm = null;
+ this.engineParams = null;
+
+ //
+ // basic key check
+ //
+ if (!(key instanceof SecretKey))
+ {
+ throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
+ }
+
+ //
+ // for RC5-64 we must have some default parameters
+ //
+ if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64"))
+ {
+ throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in.");
+ }
+
+ //
+ // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it).
+ //
+ if (key instanceof JCEPBEKey)
+ {
+ JCEPBEKey k = (JCEPBEKey)key;
+
+ if (k.getOID() != null)
+ {
+ pbeAlgorithm = k.getOID().getId();
+ }
+ else
+ {
+ pbeAlgorithm = k.getAlgorithm();
+ }
+
+ if (k.getParam() != null)
+ {
+ param = k.getParam();
+ pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount());
+ }
+ else if (params instanceof PBEParameterSpec)
+ {
+ pbeSpec = (PBEParameterSpec)params;
+ param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName());
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
+ }
+
+ if (param instanceof ParametersWithIV)
+ {
+ ivParam = (ParametersWithIV)param;
+ }
+ }
+ else if (params == null)
+ {
+ param = new KeyParameter(key.getEncoded());
+ }
+ else if (params instanceof IvParameterSpec)
+ {
+ if (ivLength != 0)
+ {
+ IvParameterSpec p = (IvParameterSpec)params;
+
+ if (p.getIV().length != ivLength && !isAEADModeName(modeName))
+ {
+ throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long.");
+ }
+
+ param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV());
+ ivParam = (ParametersWithIV)param;
+ }
+ else
+ {
+ if (modeName != null && modeName.equals("ECB"))
+ {
+ throw new InvalidAlgorithmParameterException("ECB mode does not use an IV");
+ }
+
+ param = new KeyParameter(key.getEncoded());
+ }
+ }
+ /*
+ else if (params instanceof GOST28147ParameterSpec)
+ {
+ GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params;
+
+ param = new ParametersWithSBox(
+ new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox());
+
+ if (gost28147Param.getIV() != null && ivLength != 0)
+ {
+ param = new ParametersWithIV(param, gost28147Param.getIV());
+ ivParam = (ParametersWithIV)param;
+ }
+ }
+ else if (params instanceof RC2ParameterSpec)
+ {
+ RC2ParameterSpec rc2Param = (RC2ParameterSpec)params;
+
+ param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits());
+
+ if (rc2Param.getIV() != null && ivLength != 0)
+ {
+ param = new ParametersWithIV(param, rc2Param.getIV());
+ ivParam = (ParametersWithIV)param;
+ }
+ }
+ else if (params instanceof RC5ParameterSpec)
+ {
+ RC5ParameterSpec rc5Param = (RC5ParameterSpec)params;
+
+ param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds());
+ if (baseEngine.getAlgorithmName().startsWith("RC5"))
+ {
+ if (baseEngine.getAlgorithmName().equals("RC5-32"))
+ {
+ if (rc5Param.getWordSize() != 32)
+ {
+ throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + ".");
+ }
+ }
+ else if (baseEngine.getAlgorithmName().equals("RC5-64"))
+ {
+ if (rc5Param.getWordSize() != 64)
+ {
+ throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + ".");
+ }
+ }
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5.");
+ }
+ if ((rc5Param.getIV() != null) && (ivLength != 0))
+ {
+ param = new ParametersWithIV(param, rc5Param.getIV());
+ ivParam = (ParametersWithIV)param;
+ }
+ }
+ */
+ else
+ {
+ throw new InvalidAlgorithmParameterException("unknown parameter type.");
+ }
+
+ if ((ivLength != 0) && !(param instanceof ParametersWithIV))
+ {
+ SecureRandom ivRandom = random;
+
+ if (ivRandom == null)
+ {
+ ivRandom = new SecureRandom();
+ }
+
+ if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
+ {
+ byte[] iv = new byte[ivLength];
+
+ ivRandom.nextBytes(iv);
+ param = new ParametersWithIV(param, iv);
+ ivParam = (ParametersWithIV)param;
+ }
+ else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0)
+ {
+ throw new InvalidAlgorithmParameterException("no IV set when one expected");
+ }
+ }
+
+ if (random != null && padded)
+ {
+ param = new ParametersWithRandom(param, random);
+ }
+
+ try
+ {
+ switch (opmode)
+ {
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.WRAP_MODE:
+ cipher.init(true, param);
+ break;
+ case Cipher.DECRYPT_MODE:
+ case Cipher.UNWRAP_MODE:
+ cipher.init(false, param);
+ break;
+ default:
+ throw new InvalidParameterException("unknown opmode " + opmode + " passed");
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidKeyException(e.getMessage());
+ }
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ AlgorithmParameterSpec paramSpec = null;
+
+ if (params != null)
+ {
+ for (int i = 0; i != availableSpecs.length; i++)
+ {
+ try
+ {
+ paramSpec = params.getParameterSpec(availableSpecs[i]);
+ break;
+ }
+ catch (Exception e)
+ {
+ // try again if possible
+ }
+ }
+
+ if (paramSpec == null)
+ {
+ throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
+ }
+ }
+
+ engineInit(opmode, key, paramSpec, random);
+
+ engineParams = params;
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ try
+ {
+ engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new InvalidKeyException(e.getMessage());
+ }
+ }
+
+ protected byte[] engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ {
+ int length = cipher.getUpdateOutputSize(inputLen);
+
+ if (length > 0)
+ {
+ byte[] out = new byte[length];
+
+ int len = cipher.processBytes(input, inputOffset, inputLen, out, 0);
+
+ if (len == 0)
+ {
+ return null;
+ }
+ else if (len != out.length)
+ {
+ byte[] tmp = new byte[len];
+
+ System.arraycopy(out, 0, tmp, 0, len);
+
+ return tmp;
+ }
+
+ return out;
+ }
+
+ cipher.processBytes(input, inputOffset, inputLen, null, 0);
+
+ return null;
+ }
+
+ protected int engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException
+ {
+ try
+ {
+ return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
+ }
+ catch (DataLengthException e)
+ {
+ throw new ShortBufferException(e.getMessage());
+ }
+ }
+
+ protected byte[] engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ int len = 0;
+ byte[] tmp = new byte[engineGetOutputSize(inputLen)];
+
+ if (inputLen != 0)
+ {
+ len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0);
+ }
+
+ try
+ {
+ len += cipher.doFinal(tmp, len);
+ }
+ catch (DataLengthException e)
+ {
+ throw new IllegalBlockSizeException(e.getMessage());
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new BadPaddingException(e.getMessage());
+ }
+
+ if (len == tmp.length)
+ {
+ return tmp;
+ }
+
+ byte[] out = new byte[len];
+
+ System.arraycopy(tmp, 0, out, 0, len);
+
+ return out;
+ }
+
+ protected int engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ int len = 0;
+
+ if (inputLen != 0)
+ {
+ len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
+ }
+
+ try
+ {
+ return (len + cipher.doFinal(output, outputOffset + len));
+ }
+ catch (DataLengthException e)
+ {
+ throw new IllegalBlockSizeException(e.getMessage());
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new BadPaddingException(e.getMessage());
+ }
+ }
+
+ private boolean isAEADModeName(
+ String modeName)
+ {
+ return "CCM".equals(modeName) || "EAX".equals(modeName) || "GCM".equals(modeName);
+ }
+
+ /*
+ * The ciphers that inherit from us.
+ */
+
+ /**
+ * DES
+ */
+ /*
+ static public class DES
+ extends JCEBlockCipher
+ {
+ public DES()
+ {
+ super(new DESEngine());
+ }
+ }
+ */
+
+ /**
+ * DESCBC
+ */
+ /*
+ static public class DESCBC
+ extends JCEBlockCipher
+ {
+ public DESCBC()
+ {
+ super(new CBCBlockCipher(new DESEngine()), 64);
+ }
+ }
+ */
+
+ /**
+ * DESede
+ */
+ /*
+ static public class DESede
+ extends JCEBlockCipher
+ {
+ public DESede()
+ {
+ super(new DESedeEngine());
+ }
+ }
+ */
+
+ /**
+ * DESedeCBC
+ */
+ /*
+ static public class DESedeCBC
+ extends JCEBlockCipher
+ {
+ public DESedeCBC()
+ {
+ super(new CBCBlockCipher(new DESedeEngine()), 64);
+ }
+ }
+ */
+
+ /**
+ * GOST28147
+ */
+ /*
+ static public class GOST28147
+ extends JCEBlockCipher
+ {
+ public GOST28147()
+ {
+ super(new GOST28147Engine());
+ }
+ }
+
+ static public class GOST28147cbc
+ extends JCEBlockCipher
+ {
+ public GOST28147cbc()
+ {
+ super(new CBCBlockCipher(new GOST28147Engine()), 64);
+ }
+ }
+ */
+
+ /**
+ * SKIPJACK
+ */
+ /*
+ static public class Skipjack
+ extends JCEBlockCipher
+ {
+ public Skipjack()
+ {
+ super(new SkipjackEngine());
+ }
+ }
+ */
+
+ /**
+ * Blowfish
+ */
+ /*
+ static public class Blowfish
+ extends JCEBlockCipher
+ {
+ public Blowfish()
+ {
+ super(new BlowfishEngine());
+ }
+ }
+ */
+
+ /**
+ * Blowfish CBC
+ */
+ /*
+ static public class BlowfishCBC
+ extends JCEBlockCipher
+ {
+ public BlowfishCBC()
+ {
+ super(new CBCBlockCipher(new BlowfishEngine()), 64);
+ }
+ }
+ */
+
+ /**
+ * Twofish
+ */
+ static public class Twofish
+ extends JCEBlockCipher
+ {
+ public Twofish()
+ {
+ super(new TwofishEngine());
+ }
+ }
+
+ /**
+ * RC2
+ */
+ /*
+ static public class RC2
+ extends JCEBlockCipher
+ {
+ public RC2()
+ {
+ super(new RC2Engine());
+ }
+ }
+ */
+
+ /**
+ * RC2CBC
+ */
+ /*
+ static public class RC2CBC
+ extends JCEBlockCipher
+ {
+ public RC2CBC()
+ {
+ super(new CBCBlockCipher(new RC2Engine()), 64);
+ }
+ }
+ */
+
+ /**
+ * RC5
+ */
+ /*
+ static public class RC5
+ extends JCEBlockCipher
+ {
+ public RC5()
+ {
+ super(new RC532Engine());
+ }
+ }
+ */
+
+ /**
+ * RC564
+ */
+ /*
+ static public class RC564
+ extends JCEBlockCipher
+ {
+ public RC564()
+ {
+ super(new RC564Engine());
+ }
+ }
+ */
+ /**
+ * RC6
+ */
+ /*
+ static public class RC6
+ extends JCEBlockCipher
+ {
+ public RC6()
+ {
+ super(new RC6Engine());
+ }
+ }
+
+ /**
+ * AES
+ */
+ /*
+ static public class AES
+ extends JCEBlockCipher
+ {
+ public AES()
+ {
+ super(new AESFastEngine());
+ }
+ }
+
+ /**
+ * AESCBC
+ */
+ /*
+ static public class AESCBC
+ extends JCEBlockCipher
+ {
+ public AESCBC()
+ {
+ super(new CBCBlockCipher(new AESFastEngine()), 128);
+ }
+ }
+
+ /**
+ * AESCFB
+ */
+ /*
+ static public class AESCFB
+ extends JCEBlockCipher
+ {
+ public AESCFB()
+ {
+ super(new CFBBlockCipher(new AESFastEngine(), 128), 128);
+ }
+ }
+
+ /**
+ * AESOFB
+ */
+ /*
+ static public class AESOFB
+ extends JCEBlockCipher
+ {
+ public AESOFB()
+ {
+ super(new OFBBlockCipher(new AESFastEngine(), 128), 128);
+ }
+ }
+
+ /**
+ * Rijndael
+ */
+ /*
+ static public class Rijndael
+ extends JCEBlockCipher
+ {
+ public Rijndael()
+ {
+ super(new RijndaelEngine());
+ }
+ }
+
+ /**
+ * Serpent
+ */
+ /*
+ static public class Serpent
+ extends JCEBlockCipher
+ {
+ public Serpent()
+ {
+ super(new SerpentEngine());
+ }
+ }
+
+
+
+ /**
+ * CAST5
+ */
+ /*
+ static public class CAST5
+ extends JCEBlockCipher
+ {
+ public CAST5()
+ {
+ super(new CAST5Engine());
+ }
+ }
+
+ /**
+ * CAST5 CBC
+ */
+ /*
+ static public class CAST5CBC
+ extends JCEBlockCipher
+ {
+ public CAST5CBC()
+ {
+ super(new CBCBlockCipher(new CAST5Engine()), 64);
+ }
+ }
+
+ /**
+ * CAST6
+ */
+ /*
+ static public class CAST6
+ extends JCEBlockCipher
+ {
+ public CAST6()
+ {
+ super(new CAST6Engine());
+ }
+ }
+
+ /**
+ * TEA
+ */
+ /*
+ static public class TEA
+ extends JCEBlockCipher
+ {
+ public TEA()
+ {
+ super(new TEAEngine());
+ }
+ }
+
+ /**
+ * XTEA
+ */
+ /*
+ static public class XTEA
+ extends JCEBlockCipher
+ {
+ public XTEA()
+ {
+ super(new XTEAEngine());
+ }
+ }
+
+ /**
+ * SEED
+ */
+ /*
+ static public class SEED
+ extends JCEBlockCipher
+ {
+ public SEED()
+ {
+ super(new SEEDEngine());
+ }
+ }
+
+ /**
+ * PBEWithMD5AndDES
+ */
+ /*
+ static public class PBEWithMD5AndDES
+ extends JCEBlockCipher
+ {
+ public PBEWithMD5AndDES()
+ {
+ super(new CBCBlockCipher(new DESEngine()));
+ }
+ }
+
+ /**
+ * PBEWithMD5AndRC2
+ */
+ /*
+ static public class PBEWithMD5AndRC2
+ extends JCEBlockCipher
+ {
+ public PBEWithMD5AndRC2()
+ {
+ super(new CBCBlockCipher(new RC2Engine()));
+ }
+ }
+
+ /**
+ * PBEWithSHA1AndDES
+ */
+ /*
+ static public class PBEWithSHA1AndDES
+ extends JCEBlockCipher
+ {
+ public PBEWithSHA1AndDES()
+ {
+ super(new CBCBlockCipher(new DESEngine()));
+ }
+ }
+
+ /**
+ * PBEWithSHA1AndRC2
+ */
+ /*
+ static public class PBEWithSHA1AndRC2
+ extends JCEBlockCipher
+ {
+ public PBEWithSHA1AndRC2()
+ {
+ super(new CBCBlockCipher(new RC2Engine()));
+ }
+ }
+
+ /**
+ * PBEWithSHAAnd3-KeyTripleDES-CBC
+ */
+ /*
+ static public class PBEWithSHAAndDES3Key
+ extends JCEBlockCipher
+ {
+ public PBEWithSHAAndDES3Key()
+ {
+ super(new CBCBlockCipher(new DESedeEngine()));
+ }
+ }
+
+ /**
+ * PBEWithSHAAnd2-KeyTripleDES-CBC
+ */
+ /*
+ static public class PBEWithSHAAndDES2Key
+ extends JCEBlockCipher
+ {
+ public PBEWithSHAAndDES2Key()
+ {
+ super(new CBCBlockCipher(new DESedeEngine()));
+ }
+ }
+
+ /**
+ * PBEWithSHAAnd128BitRC2-CBC
+ */
+ /*
+ static public class PBEWithSHAAnd128BitRC2
+ extends JCEBlockCipher
+ {
+ public PBEWithSHAAnd128BitRC2()
+ {
+ super(new CBCBlockCipher(new RC2Engine()));
+ }
+ }
+
+ /**
+ * PBEWithSHAAnd40BitRC2-CBC
+ */
+ /*
+ static public class PBEWithSHAAnd40BitRC2
+ extends JCEBlockCipher
+ {
+ public PBEWithSHAAnd40BitRC2()
+ {
+ super(new CBCBlockCipher(new RC2Engine()));
+ }
+ }
+
+ /**
+ * PBEWithSHAAndTwofish-CBC
+ */
+
+ static public class PBEWithSHAAndTwofish
+ extends JCEBlockCipher
+ {
+ public PBEWithSHAAndTwofish()
+ {
+ super(new CBCBlockCipher(new TwofishEngine()));
+ }
+ }
+
+ /**
+ * PBEWithAES-CBC
+ */
+ /*
+ static public class PBEWithAESCBC
+ extends JCEBlockCipher
+ {
+ public PBEWithAESCBC()
+ {
+ super(new CBCBlockCipher(new AESFastEngine()));
+ }
+ }
+ */
+
+ static private interface GenericBlockCipher
+ {
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ public boolean wrapOnNoPadding();
+
+ public String getAlgorithmName();
+
+ public BlockCipher getUnderlyingCipher();
+
+ public int getOutputSize(int len);
+
+ public int getUpdateOutputSize(int len);
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException;
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException;
+ }
+
+ private static class BufferedGenericBlockCipher
+ implements GenericBlockCipher
+ {
+ private BufferedBlockCipher cipher;
+
+ BufferedGenericBlockCipher(BufferedBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ BufferedGenericBlockCipher(BlockCipher cipher)
+ {
+ this.cipher = new PaddedBufferedBlockCipher(cipher);
+ }
+
+ /*
+ BufferedGenericBlockCipher(BlockCipher cipher, BlockCipherPadding padding)
+ {
+ this.cipher = new PaddedBufferedBlockCipher(cipher, padding);
+ }
+ */
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ cipher.init(forEncryption, params);
+ }
+
+ public boolean wrapOnNoPadding()
+ {
+ return !(cipher instanceof CTSBlockCipher);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName();
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher.getUnderlyingCipher();
+ }
+
+ public int getOutputSize(int len)
+ {
+ return cipher.getOutputSize(len);
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ return cipher.getUpdateOutputSize(len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
+ {
+ return cipher.processByte(in, out, outOff);
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
+ {
+ return cipher.processBytes(in, inOff, len, out, outOff);
+ }
+
+ public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
+ {
+ return cipher.doFinal(out, outOff);
+ }
+ }
+
+ /*
+ private static class AEADGenericBlockCipher
+ implements GenericBlockCipher
+ {
+ private AEADBlockCipher cipher;
+
+ AEADGenericBlockCipher(AEADBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ cipher.init(forEncryption, params);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName();
+ }
+
+ public boolean wrapOnNoPadding()
+ {
+ return false;
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher.getUnderlyingCipher();
+ }
+
+ public int getOutputSize(int len)
+ {
+ return cipher.getOutputSize(len);
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ return cipher.getUpdateOutputSize(len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff) throws DataLengthException
+ {
+ return cipher.processByte(in, out, outOff);
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException
+ {
+ return cipher.processBytes(in, inOff, len, out, outOff);
+ }
+
+ public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException
+ {
+ return cipher.doFinal(out, outOff);
+ }
+ }
+ */
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEPBEKey.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEPBEKey.java
new file mode 100644
index 00000000..810a9e94
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEPBEKey.java
@@ -0,0 +1,152 @@
+package org.bouncycastle.jce.provider;
+
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.PBEKeySpec;
+
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+@SuppressWarnings("serial")
+public class JCEPBEKey
+ implements PBEKey
+{
+ String algorithm;
+ DERObjectIdentifier oid;
+ int type;
+ int digest;
+ int keySize;
+ int ivSize;
+ CipherParameters param;
+ PBEKeySpec pbeKeySpec;
+ boolean tryWrong = false;
+
+ /**
+ * @param param
+ */
+ public JCEPBEKey(
+ String algorithm,
+ DERObjectIdentifier oid,
+ int type,
+ int digest,
+ int keySize,
+ int ivSize,
+ PBEKeySpec pbeKeySpec,
+ CipherParameters param)
+ {
+ this.algorithm = algorithm;
+ this.oid = oid;
+ this.type = type;
+ this.digest = digest;
+ this.keySize = keySize;
+ this.ivSize = ivSize;
+ this.pbeKeySpec = pbeKeySpec;
+ this.param = param;
+ }
+
+ public String getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public String getFormat()
+ {
+ return "RAW";
+ }
+
+ public byte[] getEncoded()
+ {
+ if (param != null)
+ {
+ KeyParameter kParam;
+
+ if (param instanceof ParametersWithIV)
+ {
+ kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
+ }
+ else
+ {
+ kParam = (KeyParameter)param;
+ }
+
+ return kParam.getKey();
+ }
+ else
+ {
+ if (type == PBE.PKCS12)
+ {
+ return PBEParametersGenerator.PKCS12PasswordToBytes(pbeKeySpec.getPassword());
+ }
+ else
+ {
+ return PBEParametersGenerator.PKCS5PasswordToBytes(pbeKeySpec.getPassword());
+ }
+ }
+ }
+
+ int getType()
+ {
+ return type;
+ }
+
+ int getDigest()
+ {
+ return digest;
+ }
+
+ int getKeySize()
+ {
+ return keySize;
+ }
+
+ int getIvSize()
+ {
+ return ivSize;
+ }
+
+ CipherParameters getParam()
+ {
+ return param;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.interfaces.PBEKey#getPassword()
+ */
+ public char[] getPassword()
+ {
+ return pbeKeySpec.getPassword();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.interfaces.PBEKey#getSalt()
+ */
+ public byte[] getSalt()
+ {
+ return pbeKeySpec.getSalt();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.interfaces.PBEKey#getIterationCount()
+ */
+ public int getIterationCount()
+ {
+ return pbeKeySpec.getIterationCount();
+ }
+
+ public DERObjectIdentifier getOID()
+ {
+ return oid;
+ }
+
+ void setTryWrongPKCS12Zero(boolean tryWrong)
+ {
+ this.tryWrong = tryWrong;
+ }
+
+ boolean shouldTryWrongPKCS12()
+ {
+ return tryWrong;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEStreamCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEStreamCipher.java
new file mode 100644
index 00000000..d366c10b
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/JCEStreamCipher.java
@@ -0,0 +1,622 @@
+package org.bouncycastle.jce.provider;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.StreamBlockCipher;
+import org.bouncycastle.crypto.StreamCipher;
+//import org.bouncycastle.crypto.engines.BlowfishEngine;
+//import org.bouncycastle.crypto.engines.DESEngine;
+//import org.bouncycastle.crypto.engines.DESedeEngine;
+//import org.bouncycastle.crypto.engines.HC128Engine;
+//import org.bouncycastle.crypto.engines.HC256Engine;
+//import org.bouncycastle.crypto.engines.RC4Engine;
+import org.bouncycastle.crypto.engines.Salsa20Engine;
+//import org.bouncycastle.crypto.engines.SkipjackEngine;
+import org.bouncycastle.crypto.engines.TwofishEngine;
+//import org.bouncycastle.crypto.engines.VMPCEngine;
+//import org.bouncycastle.crypto.engines.VMPCKSA3Engine;
+import org.bouncycastle.crypto.modes.CFBBlockCipher;
+import org.bouncycastle.crypto.modes.OFBBlockCipher;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.RC5ParameterSpec;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+@SuppressWarnings("unchecked")
+public class JCEStreamCipher
+ extends WrapCipherSpi implements PBE
+{
+ //
+ // specs we can handle.
+ //
+ private Class[] availableSpecs =
+ {
+ RC2ParameterSpec.class,
+ RC5ParameterSpec.class,
+ IvParameterSpec.class,
+ PBEParameterSpec.class
+ };
+
+ private StreamCipher cipher;
+ private ParametersWithIV ivParam;
+
+ private int ivLength = 0;
+
+ private PBEParameterSpec pbeSpec = null;
+ private String pbeAlgorithm = null;
+
+ protected JCEStreamCipher(
+ StreamCipher engine,
+ int ivLength)
+ {
+ cipher = engine;
+ this.ivLength = ivLength;
+ }
+
+ protected JCEStreamCipher(
+ BlockCipher engine,
+ int ivLength)
+ {
+ this.ivLength = ivLength;
+
+ cipher = new StreamBlockCipher(engine);
+ }
+
+ protected int engineGetBlockSize()
+ {
+ return 0;
+ }
+
+ protected byte[] engineGetIV()
+ {
+ return (ivParam != null) ? ivParam.getIV() : null;
+ }
+
+ protected int engineGetKeySize(
+ Key key)
+ {
+ return key.getEncoded().length * 8;
+ }
+
+ protected int engineGetOutputSize(
+ int inputLen)
+ {
+ return inputLen;
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ if (engineParams == null)
+ {
+ if (pbeSpec != null)
+ {
+ try
+ {
+ AlgorithmParameters engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, "BC");
+ engineParams.init(pbeSpec);
+
+ return engineParams;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ }
+
+ return engineParams;
+ }
+
+ /**
+ * should never be called.
+ */
+ protected void engineSetMode(
+ String mode)
+ {
+ if (!mode.equalsIgnoreCase("ECB"))
+ {
+ throw new IllegalArgumentException("can't support mode " + mode);
+ }
+ }
+
+ /**
+ * should never be called.
+ */
+ protected void engineSetPadding(
+ String padding)
+ throws NoSuchPaddingException
+ {
+ if (!padding.equalsIgnoreCase("NoPadding"))
+ {
+ throw new NoSuchPaddingException("Padding " + padding + " unknown.");
+ }
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+
+ this.pbeSpec = null;
+ this.pbeAlgorithm = null;
+
+ this.engineParams = null;
+
+ //
+ // basic key check
+ //
+ if (!(key instanceof SecretKey))
+ {
+ throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
+ }
+
+ if (key instanceof JCEPBEKey)
+ {
+ JCEPBEKey k = (JCEPBEKey)key;
+
+ if (k.getOID() != null)
+ {
+ pbeAlgorithm = k.getOID().getId();
+ }
+ else
+ {
+ pbeAlgorithm = k.getAlgorithm();
+ }
+
+ if (k.getParam() != null)
+ {
+ param = k.getParam();
+ pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount());
+ }
+ else if (params instanceof PBEParameterSpec)
+ {
+ param = PBE.Util.makePBEParameters(k, params, cipher.getAlgorithmName());
+ pbeSpec = (PBEParameterSpec)params;
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
+ }
+
+ if (k.getIvSize() != 0)
+ {
+ ivParam = (ParametersWithIV)param;
+ }
+ }
+ else if (params == null)
+ {
+ param = new KeyParameter(key.getEncoded());
+ }
+ else if (params instanceof IvParameterSpec)
+ {
+ param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV());
+ ivParam = (ParametersWithIV)param;
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown parameter type.");
+ }
+
+ if ((ivLength != 0) && !(param instanceof ParametersWithIV))
+ {
+ SecureRandom ivRandom = random;
+
+ if (ivRandom == null)
+ {
+ ivRandom = new SecureRandom();
+ }
+
+ if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
+ {
+ byte[] iv = new byte[ivLength];
+
+ ivRandom.nextBytes(iv);
+ param = new ParametersWithIV(param, iv);
+ ivParam = (ParametersWithIV)param;
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException("no IV set when one expected");
+ }
+ }
+
+ switch (opmode)
+ {
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.WRAP_MODE:
+ cipher.init(true, param);
+ break;
+ case Cipher.DECRYPT_MODE:
+ case Cipher.UNWRAP_MODE:
+ cipher.init(false, param);
+ break;
+ default:
+ System.out.println("eeek!");
+ }
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ AlgorithmParameterSpec paramSpec = null;
+
+ if (params != null)
+ {
+ for (int i = 0; i != availableSpecs.length; i++)
+ {
+ try
+ {
+ paramSpec = params.getParameterSpec(availableSpecs[i]);
+ break;
+ }
+ catch (Exception e)
+ {
+ continue;
+ }
+ }
+
+ if (paramSpec == null)
+ {
+ throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
+ }
+ }
+
+ engineInit(opmode, key, paramSpec, random);
+ engineParams = params;
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ try
+ {
+ engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new InvalidKeyException(e.getMessage());
+ }
+ }
+
+ protected byte[] engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ {
+ byte[] out = new byte[inputLen];
+
+ cipher.processBytes(input, inputOffset, inputLen, out, 0);
+
+ return out;
+ }
+
+ protected int engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException
+ {
+ try
+ {
+ cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
+
+ return inputLen;
+ }
+ catch (DataLengthException e)
+ {
+ throw new ShortBufferException(e.getMessage());
+ }
+ }
+
+ protected byte[] engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ {
+ if (inputLen != 0)
+ {
+ byte[] out = engineUpdate(input, inputOffset, inputLen);
+
+ cipher.reset();
+
+ return out;
+ }
+
+ cipher.reset();
+
+ return new byte[0];
+ }
+
+ protected int engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ {
+ if (inputLen != 0)
+ {
+ cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
+ }
+
+ cipher.reset();
+
+ return inputLen;
+ }
+
+ /*
+ * The ciphers that inherit from us.
+ */
+
+ /**
+ * DES
+ */
+ /*
+ static public class DES_CFB8
+ extends JCEStreamCipher
+ {
+ public DES_CFB8()
+ {
+ super(new CFBBlockCipher(new DESEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * DESede
+ */
+ /*
+ static public class DESede_CFB8
+ extends JCEStreamCipher
+ {
+ public DESede_CFB8()
+ {
+ super(new CFBBlockCipher(new DESedeEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * SKIPJACK
+ */
+ /*
+ static public class Skipjack_CFB8
+ extends JCEStreamCipher
+ {
+ public Skipjack_CFB8()
+ {
+ super(new CFBBlockCipher(new SkipjackEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * Blowfish
+ */
+ /*
+ static public class Blowfish_CFB8
+ extends JCEStreamCipher
+ {
+ public Blowfish_CFB8()
+ {
+ super(new CFBBlockCipher(new BlowfishEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * Twofish
+ */
+ static public class Twofish_CFB8
+ extends JCEStreamCipher
+ {
+ public Twofish_CFB8()
+ {
+ super(new CFBBlockCipher(new TwofishEngine(), 8), 128);
+ }
+ }
+
+ /**
+ * DES
+ */
+ /*
+ static public class DES_OFB8
+ extends JCEStreamCipher
+ {
+ public DES_OFB8()
+ {
+ super(new OFBBlockCipher(new DESEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * DESede
+ */
+ /*
+ static public class DESede_OFB8
+ extends JCEStreamCipher
+ {
+ public DESede_OFB8()
+ {
+ super(new OFBBlockCipher(new DESedeEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * SKIPJACK
+ */
+ /*
+ static public class Skipjack_OFB8
+ extends JCEStreamCipher
+ {
+ public Skipjack_OFB8()
+ {
+ super(new OFBBlockCipher(new SkipjackEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * Blowfish
+ */
+ /*
+ static public class Blowfish_OFB8
+ extends JCEStreamCipher
+ {
+ public Blowfish_OFB8()
+ {
+ super(new OFBBlockCipher(new BlowfishEngine(), 8), 64);
+ }
+ }
+ */
+
+ /**
+ * Twofish
+ */
+ static public class Twofish_OFB8
+ extends JCEStreamCipher
+ {
+ public Twofish_OFB8()
+ {
+ super(new OFBBlockCipher(new TwofishEngine(), 8), 128);
+ }
+ }
+
+ /**
+ * RC4
+ */
+ /*
+ static public class RC4
+ extends JCEStreamCipher
+ {
+ public RC4()
+ {
+ super(new RC4Engine(), 0);
+ }
+ }
+ */
+
+ /**
+ * PBEWithSHAAnd128BitRC4
+ */
+ /*
+ static public class PBEWithSHAAnd128BitRC4
+ extends JCEStreamCipher
+ {
+ public PBEWithSHAAnd128BitRC4()
+ {
+ super(new RC4Engine(), 0);
+ }
+ }
+ */
+ /**
+ * PBEWithSHAAnd40BitRC4
+ */
+ /*
+ static public class PBEWithSHAAnd40BitRC4
+ extends JCEStreamCipher
+ {
+ public PBEWithSHAAnd40BitRC4()
+ {
+ super(new RC4Engine(), 0);
+ }
+ }
+ */
+
+ /**
+ * Salsa20
+ */
+ static public class Salsa20
+ extends JCEStreamCipher
+ {
+ public Salsa20()
+ {
+ super(new Salsa20Engine(), 8);
+ }
+ }
+
+ /**
+ * HC-128
+ */
+ /*
+ static public class HC128
+ extends JCEStreamCipher
+ {
+ public HC128()
+ {
+ super(new HC128Engine(), 16);
+ }
+ }
+ */
+
+ /**
+ * HC-256
+ */
+ /*
+ static public class HC256
+ extends JCEStreamCipher
+ {
+ public HC256()
+ {
+ super(new HC256Engine(), 32);
+ }
+ }
+ */
+
+ /**
+ * VMPC
+ */
+ /*
+ static public class VMPC
+ extends JCEStreamCipher
+ {
+ public VMPC()
+ {
+ super(new VMPCEngine(), 16);
+ }
+ }
+ */
+
+ /**
+ * VMPC-KSA3
+ */
+ /*
+ static public class VMPCKSA3
+ extends JCEStreamCipher
+ {
+ public VMPCKSA3()
+ {
+ super(new VMPCKSA3Engine(), 16);
+ }
+ }
+ */
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PBE.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PBE.java
new file mode 100644
index 00000000..7bd1600f
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PBE.java
@@ -0,0 +1,281 @@
+package org.bouncycastle.jce.provider;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.digests.MD2Digest;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.crypto.digests.RIPEMD160Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.digests.TigerDigest;
+import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
+import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
+import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
+import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
+import org.bouncycastle.crypto.params.DESParameters;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+public interface PBE
+{
+ //
+ // PBE Based encryption constants - by default we do PKCS12 with SHA-1
+ //
+ static final int MD5 = 0;
+ static final int SHA1 = 1;
+ static final int RIPEMD160 = 2;
+ static final int TIGER = 3;
+ static final int SHA256 = 4;
+ static final int MD2 = 5;
+
+ static final int PKCS5S1 = 0;
+ static final int PKCS5S2 = 1;
+ static final int PKCS12 = 2;
+ static final int OPENSSL = 3;
+
+ /**
+ * uses the appropriate mixer to generate the key and IV if necessary.
+ */
+ static class Util
+ {
+ static private PBEParametersGenerator makePBEGenerator(
+ int type,
+ int hash)
+ {
+ PBEParametersGenerator generator;
+
+ if (type == PKCS5S1)
+ {
+ switch (hash)
+ {
+ case MD2:
+ generator = new PKCS5S1ParametersGenerator(new MD2Digest());
+ break;
+ case MD5:
+ generator = new PKCS5S1ParametersGenerator(new MD5Digest());
+ break;
+ case SHA1:
+ generator = new PKCS5S1ParametersGenerator(new SHA1Digest());
+ break;
+ default:
+ throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1.");
+ }
+ }
+ else if (type == PKCS5S2)
+ {
+ generator = new PKCS5S2ParametersGenerator();
+ }
+ else if (type == PKCS12)
+ {
+ switch (hash)
+ {
+ case MD2:
+ generator = new PKCS12ParametersGenerator(new MD2Digest());
+ break;
+ case MD5:
+ generator = new PKCS12ParametersGenerator(new MD5Digest());
+ break;
+ case SHA1:
+ generator = new PKCS12ParametersGenerator(new SHA1Digest());
+ break;
+ case RIPEMD160:
+ generator = new PKCS12ParametersGenerator(new RIPEMD160Digest());
+ break;
+ case TIGER:
+ generator = new PKCS12ParametersGenerator(new TigerDigest());
+ break;
+ case SHA256:
+ generator = new PKCS12ParametersGenerator(new SHA256Digest());
+ break;
+ default:
+ throw new IllegalStateException("unknown digest scheme for PBE encryption.");
+ }
+ }
+ else
+ {
+ generator = new OpenSSLPBEParametersGenerator();
+ }
+
+ return generator;
+ }
+
+ /**
+ * construct a key and iv (if necessary) suitable for use with a
+ * Cipher.
+ */
+ static CipherParameters makePBEParameters(
+ JCEPBEKey pbeKey,
+ AlgorithmParameterSpec spec,
+ String targetAlgorithm)
+ {
+ if ((spec == null) || !(spec instanceof PBEParameterSpec))
+ {
+ throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
+ }
+
+ PBEParameterSpec pbeParam = (PBEParameterSpec)spec;
+ PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
+ byte[] key = pbeKey.getEncoded();
+ CipherParameters param;
+
+ if (pbeKey.shouldTryWrongPKCS12())
+ {
+ key = new byte[2];
+ }
+
+ generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
+
+ if (pbeKey.getIvSize() != 0)
+ {
+ param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize());
+ }
+ else
+ {
+ param = generator.generateDerivedParameters(pbeKey.getKeySize());
+ }
+
+ if (targetAlgorithm.startsWith("DES"))
+ {
+ if (param instanceof ParametersWithIV)
+ {
+ KeyParameter kParam = (KeyParameter)((ParametersWithIV)param).getParameters();
+
+ DESParameters.setOddParity(kParam.getKey());
+ }
+ else
+ {
+ KeyParameter kParam = (KeyParameter)param;
+
+ DESParameters.setOddParity(kParam.getKey());
+ }
+ }
+
+ for (int i = 0; i != key.length; i++)
+ {
+ key[i] = 0;
+ }
+
+ return param;
+ }
+
+ /**
+ * generate a PBE based key suitable for a MAC algorithm, the
+ * key size is chosen according the MAC size, or the hashing algorithm,
+ * whichever is greater.
+ */
+ static CipherParameters makePBEMacParameters(
+ JCEPBEKey pbeKey,
+ AlgorithmParameterSpec spec)
+ {
+ if ((spec == null) || !(spec instanceof PBEParameterSpec))
+ {
+ throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key.");
+ }
+
+ PBEParameterSpec pbeParam = (PBEParameterSpec)spec;
+ PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest());
+ byte[] key = pbeKey.getEncoded();
+ CipherParameters param;
+
+ if (pbeKey.shouldTryWrongPKCS12())
+ {
+ key = new byte[2];
+ }
+
+ generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount());
+
+ param = generator.generateDerivedMacParameters(pbeKey.getKeySize());
+
+ for (int i = 0; i != key.length; i++)
+ {
+ key[i] = 0;
+ }
+
+ return param;
+ }
+
+ /**
+ * construct a key and iv (if necessary) suitable for use with a
+ * Cipher.
+ */
+ static CipherParameters makePBEParameters(
+ PBEKeySpec keySpec,
+ int type,
+ int hash,
+ int keySize,
+ int ivSize)
+ {
+ PBEParametersGenerator generator = makePBEGenerator(type, hash);
+ byte[] key;
+ CipherParameters param;
+
+ if (type == PKCS12)
+ {
+ key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
+ }
+ else
+ {
+ key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
+ }
+
+ generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
+
+ if (ivSize != 0)
+ {
+ param = generator.generateDerivedParameters(keySize, ivSize);
+ }
+ else
+ {
+ param = generator.generateDerivedParameters(keySize);
+ }
+
+ for (int i = 0; i != key.length; i++)
+ {
+ key[i] = 0;
+ }
+
+ return param;
+ }
+
+ /**
+ * generate a PBE based key suitable for a MAC algorithm, the
+ * key size is chosen according the MAC size, or the hashing algorithm,
+ * whichever is greater.
+ */
+ static CipherParameters makePBEMacParameters(
+ PBEKeySpec keySpec,
+ int type,
+ int hash,
+ int keySize)
+ {
+ PBEParametersGenerator generator = makePBEGenerator(type, hash);
+ byte[] key;
+ CipherParameters param;
+
+ if (type == PKCS12)
+ {
+ key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword());
+ }
+ else
+ {
+ key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword());
+ }
+
+ generator.init(key, keySpec.getSalt(), keySpec.getIterationCount());
+
+ param = generator.generateDerivedMacParameters(keySize);
+
+ for (int i = 0; i != key.length; i++)
+ {
+ key[i] = 0;
+ }
+
+ return param;
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java
new file mode 100644
index 00000000..9907b200
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/PKCS12BagAttributeCarrierImpl.java
@@ -0,0 +1,125 @@
+package org.bouncycastle.jce.provider;
+
+import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.ASN1OutputStream;
+import org.bouncycastle.asn1.ASN1InputStream;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+@SuppressWarnings("unchecked")
+class PKCS12BagAttributeCarrierImpl
+ implements PKCS12BagAttributeCarrier
+{
+ private Hashtable pkcs12Attributes;
+ private Vector pkcs12Ordering;
+
+ PKCS12BagAttributeCarrierImpl(Hashtable attributes, Vector ordering)
+ {
+ this.pkcs12Attributes = attributes;
+ this.pkcs12Ordering = ordering;
+ }
+
+ public PKCS12BagAttributeCarrierImpl()
+ {
+ this(new Hashtable(), new Vector());
+ }
+
+ public void setBagAttribute(
+ DERObjectIdentifier oid,
+ DEREncodable attribute)
+ {
+ if (pkcs12Attributes.containsKey(oid))
+ { // preserve original ordering
+ pkcs12Attributes.put(oid, attribute);
+ }
+ else
+ {
+ pkcs12Attributes.put(oid, attribute);
+ pkcs12Ordering.addElement(oid);
+ }
+ }
+
+ public DEREncodable getBagAttribute(
+ DERObjectIdentifier oid)
+ {
+ return (DEREncodable)pkcs12Attributes.get(oid);
+ }
+
+ public Enumeration getBagAttributeKeys()
+ {
+ return pkcs12Ordering.elements();
+ }
+
+ int size()
+ {
+ return pkcs12Ordering.size();
+ }
+
+ Hashtable getAttributes()
+ {
+ return pkcs12Attributes;
+ }
+
+ Vector getOrdering()
+ {
+ return pkcs12Ordering;
+ }
+
+ public void writeObject(ObjectOutputStream out)
+ throws IOException
+ {
+ if (pkcs12Ordering.size() == 0)
+ {
+ out.writeObject(new Hashtable());
+ out.writeObject(new Vector());
+ }
+ else
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ Enumeration e = this.getBagAttributeKeys();
+
+ while (e.hasMoreElements())
+ {
+ DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
+
+ aOut.writeObject(oid);
+ aOut.writeObject(pkcs12Attributes.get(oid));
+ }
+
+ out.writeObject(bOut.toByteArray());
+ }
+ }
+
+ public void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ Object obj = in.readObject();
+
+ if (obj instanceof Hashtable)
+ {
+ this.pkcs12Attributes = (Hashtable)obj;
+ this.pkcs12Ordering = (Vector)in.readObject();
+ }
+ else
+ {
+ ASN1InputStream aIn = new ASN1InputStream((byte[])obj);
+
+ DERObjectIdentifier oid;
+
+ while ((oid = (DERObjectIdentifier)aIn.readObject()) != null)
+ {
+ this.setBagAttribute(oid, aIn.readObject());
+ }
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/WrapCipherSpi.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/WrapCipherSpi.java
new file mode 100644
index 00000000..090fbf13
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/jce/provider/WrapCipherSpi.java
@@ -0,0 +1,461 @@
+package org.bouncycastle.jce.provider;
+
+/*
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+*/
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.Wrapper;
+//import org.bouncycastle.crypto.engines.DESedeEngine;
+//import org.bouncycastle.crypto.engines.DESedeWrapEngine;
+//import org.bouncycastle.crypto.engines.RC2WrapEngine;
+//import org.bouncycastle.crypto.engines.RFC3211WrapEngine;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.RC5ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+//import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public abstract class WrapCipherSpi extends CipherSpi
+ implements PBE
+{
+ //
+ // specs we can handle.
+ //
+ @SuppressWarnings("unchecked")
+ private Class[] availableSpecs =
+ {
+ IvParameterSpec.class,
+ PBEParameterSpec.class,
+ RC2ParameterSpec.class,
+ RC5ParameterSpec.class
+ };
+
+ protected int pbeType = PKCS12;
+ protected int pbeHash = SHA1;
+ protected int pbeKeySize;
+ protected int pbeIvSize;
+
+ protected AlgorithmParameters engineParams = null;
+
+ protected Wrapper wrapEngine = null;
+
+ private int ivSize;
+ private byte[] iv;
+
+ protected WrapCipherSpi()
+ {
+ }
+
+ protected WrapCipherSpi(
+ Wrapper wrapEngine)
+ {
+ this(wrapEngine, 0);
+ }
+
+ protected WrapCipherSpi(
+ Wrapper wrapEngine,
+ int ivSize)
+ {
+ this.wrapEngine = wrapEngine;
+ this.ivSize = ivSize;
+ }
+
+ protected int engineGetBlockSize()
+ {
+ return 0;
+ }
+
+ protected byte[] engineGetIV()
+ {
+ return (byte[])iv.clone();
+ }
+
+ protected int engineGetKeySize(
+ Key key)
+ {
+ return key.getEncoded().length;
+ }
+
+ protected int engineGetOutputSize(
+ int inputLen)
+ {
+ return -1;
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ return null;
+ }
+
+ protected void engineSetMode(
+ String mode)
+ throws NoSuchAlgorithmException
+ {
+ throw new NoSuchAlgorithmException("can't support mode " + mode);
+ }
+
+ protected void engineSetPadding(
+ String padding)
+ throws NoSuchPaddingException
+ {
+ throw new NoSuchPaddingException("Padding " + padding + " unknown.");
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+
+ if (key instanceof JCEPBEKey)
+ {
+ JCEPBEKey k = (JCEPBEKey)key;
+
+ if (params instanceof PBEParameterSpec)
+ {
+ param = PBE.Util.makePBEParameters(k, params, wrapEngine.getAlgorithmName());
+ }
+ else if (k.getParam() != null)
+ {
+ param = k.getParam();
+ }
+ else
+ {
+ throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
+ }
+ }
+ else
+ {
+ param = new KeyParameter(key.getEncoded());
+ }
+
+ if (params instanceof javax.crypto.spec.IvParameterSpec)
+ {
+ IvParameterSpec iv = (IvParameterSpec) params;
+ param = new ParametersWithIV(param, iv.getIV());
+ }
+
+ if (param instanceof KeyParameter && ivSize != 0)
+ {
+ iv = new byte[ivSize];
+ random.nextBytes(iv);
+ param = new ParametersWithIV(param, iv);
+ }
+
+ switch (opmode)
+ {
+ case Cipher.WRAP_MODE:
+ wrapEngine.init(true, param);
+ break;
+ case Cipher.UNWRAP_MODE:
+ wrapEngine.init(false, param);
+ break;
+ case Cipher.ENCRYPT_MODE:
+ case Cipher.DECRYPT_MODE:
+ throw new IllegalArgumentException("engine only valid for wrapping");
+ default:
+ System.out.println("eeek!");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void engineInit(
+ int opmode,
+ Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ AlgorithmParameterSpec paramSpec = null;
+
+ if (params != null)
+ {
+ for (int i = 0; i != availableSpecs.length; i++)
+ {
+ try
+ {
+ paramSpec = params.getParameterSpec(availableSpecs[i]);
+ break;
+ }
+ catch (Exception e)
+ {
+ // try next spec
+ }
+ }
+
+ if (paramSpec == null)
+ {
+ throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
+ }
+ }
+
+ engineParams = params;
+ engineInit(opmode, key, paramSpec, random);
+ }
+
+ protected void engineInit(
+ int opmode,
+ Key key,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ try
+ {
+ engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ protected byte[] engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ {
+ throw new RuntimeException("not supported for wrapping");
+ }
+
+ protected int engineUpdate(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws ShortBufferException
+ {
+ throw new RuntimeException("not supported for wrapping");
+ }
+
+ protected byte[] engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ return null;
+ }
+
+ protected int engineDoFinal(
+ byte[] input,
+ int inputOffset,
+ int inputLen,
+ byte[] output,
+ int outputOffset)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ return 0;
+ }
+
+ protected byte[] engineWrap(
+ Key key)
+ throws IllegalBlockSizeException, java.security.InvalidKeyException
+ {
+ byte[] encoded = key.getEncoded();
+ if (encoded == null)
+ {
+ throw new InvalidKeyException("Cannot wrap key, null encoding.");
+ }
+
+ try
+ {
+ if (wrapEngine == null)
+ {
+ return engineDoFinal(encoded, 0, encoded.length);
+ }
+ else
+ {
+ return wrapEngine.wrap(encoded, 0, encoded.length);
+ }
+ }
+ catch (BadPaddingException e)
+ {
+ throw new IllegalBlockSizeException(e.getMessage());
+ }
+ }
+
+ protected Key engineUnwrap(
+ byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException
+ {
+ byte[] encoded;
+ try
+ {
+ if (wrapEngine == null)
+ {
+ encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
+ }
+ else
+ {
+ encoded = wrapEngine.unwrap(wrappedKey, 0, wrappedKey.length);
+ }
+ }
+ catch (InvalidCipherTextException e)
+ {
+ throw new InvalidKeyException(e.getMessage());
+ }
+ catch (BadPaddingException e)
+ {
+ throw new InvalidKeyException(e.getMessage());
+ }
+ catch (IllegalBlockSizeException e2)
+ {
+ throw new InvalidKeyException(e2.getMessage());
+ }
+
+ if (wrappedKeyType == Cipher.SECRET_KEY)
+ {
+ return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
+ }
+ /*
+ else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY)
+ {
+
+ // * The caller doesnt know the algorithm as it is part of
+ // * the encrypted data.
+
+ ASN1InputStream bIn = new ASN1InputStream(encoded);
+ PrivateKey privKey;
+
+ try
+ {
+ ASN1Sequence s = (ASN1Sequence)bIn.readObject();
+ PrivateKeyInfo in = new PrivateKeyInfo(s);
+
+ DERObjectIdentifier oid = in.getAlgorithmId().getObjectId();
+
+
+ if (oid.equals(X9ObjectIdentifiers.id_ecPublicKey))
+ {
+ privKey = new JCEECPrivateKey(in);
+ }
+ else if (oid.equals(CryptoProObjectIdentifiers.gostR3410_94))
+ {
+ privKey = new JDKGOST3410PrivateKey(in);
+ }
+
+ else if (oid.equals(X9ObjectIdentifiers.id_dsa))
+ {
+ privKey = new JDKDSAPrivateKey(in);
+ }
+ else if (oid.equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ {
+ privKey = new JCEDHPrivateKey(in);
+ }
+ else if (oid.equals(X9ObjectIdentifiers.dhpublicnumber))
+ {
+ privKey = new JCEDHPrivateKey(in);
+ }
+ else // the old standby!
+ {
+ privKey = new JCERSAPrivateCrtKey(in);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidKeyException("Invalid key encoding.");
+ }
+
+ return privKey;
+ }
+ */
+ else
+ {
+ try
+ {
+ KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, "BC");
+ if (wrappedKeyType == Cipher.PUBLIC_KEY)
+ {
+ return kf.generatePublic(new X509EncodedKeySpec(encoded));
+ }
+ else if (wrappedKeyType == Cipher.PRIVATE_KEY)
+ {
+ return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
+ }
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new InvalidKeyException("Unknown key type " + e.getMessage());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new InvalidKeyException("Unknown key type " + e.getMessage());
+ }
+ catch (InvalidKeySpecException e2)
+ {
+ throw new InvalidKeyException("Unknown key type " + e2.getMessage());
+ }
+
+ throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
+ }
+ }
+
+ //
+ // classes that inherit directly from us
+ //
+
+
+ /*
+ public static class DESEDEWrap
+ extends WrapCipherSpi
+ {
+ public DESEDEWrap()
+ {
+ super(new DESedeWrapEngine());
+ }
+ }
+
+ public static class RC2Wrap
+ extends WrapCipherSpi
+ {
+ public RC2Wrap()
+ {
+ super(new RC2WrapEngine());
+ }
+ }
+
+ public static class RFC3211DESedeWrap
+ extends WrapCipherSpi
+ {
+ public RFC3211DESedeWrap()
+ {
+ super(new RFC3211WrapEngine(new DESedeEngine()), 8);
+ }
+ }
+ */
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Arrays.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Arrays.java
new file mode 100644
index 00000000..9600fd53
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Arrays.java
@@ -0,0 +1,214 @@
+package org.bouncycastle.util;
+
+/**
+ * General array utilities.
+ */
+public final class Arrays
+{
+ private Arrays()
+ {
+ // static class, hide constructor
+ }
+
+ public static boolean areEqual(
+ boolean[] a,
+ boolean[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * A constant time equals comparison - does not terminate early if
+ * test will fail.
+ *
+ * @param a first array
+ * @param b second array
+ * @return true if arrays equal, false otherwise.
+ */
+ public static boolean constantTimeAreEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ int nonEqual = 0;
+
+ for (int i = 0; i != a.length; i++)
+ {
+ nonEqual |= (a[i] ^ b[i]);
+ }
+
+ return nonEqual == 0;
+ }
+
+ public static boolean areEqual(
+ int[] a,
+ int[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static void fill(
+ byte[] array,
+ byte value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ long[] array,
+ long value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ short[] array,
+ short value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static int hashCode(byte[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static byte[] clone(byte[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ byte[] copy = new byte[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static int[] clone(int[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ int[] copy = new int[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Strings.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Strings.java
new file mode 100644
index 00000000..253e7226
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/Strings.java
@@ -0,0 +1,247 @@
+package org.bouncycastle.util;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Vector;
+
+public final class Strings
+{
+ public static String fromUTF8ByteArray(byte[] bytes)
+ {
+ int i = 0;
+ int length = 0;
+
+ while (i < bytes.length)
+ {
+ length++;
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ // surrogate pair
+ length++;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ i += 3;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ i += 2;
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ char[] cs = new char[length];
+
+ i = 0;
+ length = 0;
+
+ while (i < bytes.length)
+ {
+ char ch;
+
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
+ int U = codePoint - 0x10000;
+ char W1 = (char)(0xD800 | (U >> 10));
+ char W2 = (char)(0xDC00 | (U & 0x3FF));
+ cs[length++] = W1;
+ ch = W2;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ ch = (char)(((bytes[i] & 0x0f) << 12)
+ | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
+ i += 3;
+ }
+ else if ((bytes[i] & 0xd0) == 0xd0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else
+ {
+ ch = (char)(bytes[i] & 0xff);
+ i += 1;
+ }
+
+ cs[length++] = ch;
+ }
+
+ return new String(cs);
+ }
+
+ public static byte[] toUTF8ByteArray(String string)
+ {
+ return toUTF8ByteArray(string.toCharArray());
+ }
+
+ public static byte[] toUTF8ByteArray(char[] string)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ char[] c = string;
+ int i = 0;
+
+ while (i < c.length)
+ {
+ char ch = c[i];
+
+ if (ch < 0x0080)
+ {
+ bOut.write(ch);
+ }
+ else if (ch < 0x0800)
+ {
+ bOut.write(0xc0 | (ch >> 6));
+ bOut.write(0x80 | (ch & 0x3f));
+ }
+ // surrogate pair
+ else if (ch >= 0xD800 && ch <= 0xDFFF)
+ {
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (i + 1 >= c.length)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ char W1 = ch;
+ ch = c[++i];
+ char W2 = ch;
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (W1 > 0xDBFF)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
+ bOut.write(0xf0 | (codePoint >> 18));
+ bOut.write(0x80 | ((codePoint >> 12) & 0x3F));
+ bOut.write(0x80 | ((codePoint >> 6) & 0x3F));
+ bOut.write(0x80 | (codePoint & 0x3F));
+ }
+ else
+ {
+ bOut.write(0xe0 | (ch >> 12));
+ bOut.write(0x80 | ((ch >> 6) & 0x3F));
+ bOut.write(0x80 | (ch & 0x3F));
+ }
+
+ i++;
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * A locale independent version of toUpperCase.
+ *
+ * @param string input to be converted
+ * @return a US Ascii uppercase version
+ */
+ public static String toUpperCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('a' <= ch && 'z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'a' + 'A');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ /**
+ * A locale independent version of toLowerCase.
+ *
+ * @param string input to be converted
+ * @return a US ASCII lowercase version
+ */
+ public static String toLowerCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('A' <= ch && 'Z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'A' + 'a');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ public static byte[] toByteArray(String string)
+ {
+ byte[] bytes = new byte[string.length()];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ char ch = string.charAt(i);
+
+ bytes[i] = (byte)ch;
+ }
+
+ return bytes;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static String[] split(String input, char delimiter)
+ {
+ Vector v = new Vector();
+ boolean moreTokens = true;
+ String subString;
+
+ while (moreTokens)
+ {
+ int tokenLocation = input.indexOf(delimiter);
+ if (tokenLocation > 0)
+ {
+ subString = input.substring(0, tokenLocation);
+ v.addElement(subString);
+ input = input.substring(tokenLocation + 1);
+ }
+ else
+ {
+ moreTokens = false;
+ v.addElement(input);
+ }
+ }
+
+ String[] res = new String[v.size()];
+
+ for (int i = 0; i != res.length; i++)
+ {
+ res[i] = (String)v.elementAt(i);
+ }
+ return res;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Encoder.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Encoder.java
new file mode 100644
index 00000000..b0661210
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Encoder.java
@@ -0,0 +1,17 @@
+package org.bouncycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Encode and decode byte arrays (typically from binary to 7-bit ASCII
+ * encodings).
+ */
+public interface Encoder
+{
+ int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(String data, OutputStream out) throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Hex.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Hex.java
new file mode 100644
index 00000000..d69f7739
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/Hex.java
@@ -0,0 +1,131 @@
+package org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class Hex
+{
+ private static final Encoder encoder = new HexEncoder();
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("exception encoding Hex string: " + e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the Hex encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("exception decoding Hex string: " + e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("exception decoding Hex string: " + e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/HexEncoder.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/HexEncoder.java
new file mode 100644
index 00000000..0dcae291
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/encoders/HexEncoder.java
@@ -0,0 +1,172 @@
+package org.bouncycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+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'
+ };
+
+ /*
+ * set up the decoding table.
+ */
+ protected final byte[] decodingTable = new byte[128];
+
+ protected void initialiseDecodingTable()
+ {
+ for (int i = 0; i < encodingTable.length; i++)
+ {
+ decodingTable[encodingTable[i]] = (byte)i;
+ }
+
+ decodingTable['A'] = decodingTable['a'];
+ decodingTable['B'] = decodingTable['b'];
+ decodingTable['C'] = decodingTable['c'];
+ decodingTable['D'] = decodingTable['d'];
+ decodingTable['E'] = decodingTable['e'];
+ decodingTable['F'] = decodingTable['f'];
+ }
+
+ public HexEncoder()
+ {
+ initialiseDecodingTable();
+ }
+
+ /**
+ * encode the input data producing a Hex output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ for (int i = off; i < (off + length); i++)
+ {
+ int v = data[i] & 0xff;
+
+ out.write(encodingTable[(v >>> 4)]);
+ out.write(encodingTable[v & 0xf]);
+ }
+
+ return length * 2;
+ }
+
+ private boolean ignore(
+ char c)
+ {
+ return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
+ }
+
+ /**
+ * decode the Hex encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int outLen = 0;
+
+ int end = off + length;
+
+ while (end > off)
+ {
+ if (!ignore((char)data[end - 1]))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = off;
+ while (i < end)
+ {
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data[i++]];
+
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data[i++]];
+
+ out.write((b1 << 4) | b2);
+
+ outLen++;
+ }
+
+ return outLen;
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int length = 0;
+
+ int end = data.length();
+
+ while (end > 0)
+ {
+ if (!ignore(data.charAt(end - 1)))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = 0;
+ while (i < end)
+ {
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data.charAt(i++)];
+
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data.charAt(i++)];
+
+ out.write((b1 << 4) | b2);
+
+ length++;
+ }
+
+ return length;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/StreamOverflowException.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/StreamOverflowException.java
new file mode 100644
index 00000000..1dc49bb9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/StreamOverflowException.java
@@ -0,0 +1,13 @@
+package org.bouncycastle.util.io;
+
+import java.io.IOException;
+
+@SuppressWarnings("serial")
+public class StreamOverflowException
+ extends IOException
+{
+ public StreamOverflowException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/Streams.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/Streams.java
new file mode 100644
index 00000000..41560b5d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/util/io/Streams.java
@@ -0,0 +1,87 @@
+package org.bouncycastle.util.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public final class Streams
+{
+ private static int BUFFER_SIZE = 512;
+
+ public static void drain(InputStream inStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ while (inStr.read(bs, 0, bs.length) >= 0)
+ {
+ }
+ }
+
+ public static byte[] readAll(InputStream inStr)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAll(inStr, buf);
+ return buf.toByteArray();
+ }
+
+ public static byte[] readAllLimited(InputStream inStr, int limit)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAllLimited(inStr, limit, buf);
+ return buf.toByteArray();
+ }
+
+ public static int readFully(InputStream inStr, byte[] buf)
+ throws IOException
+ {
+ return readFully(inStr, buf, 0, buf.length);
+ }
+
+ public static int readFully(InputStream inStr, byte[] buf, int off, int len)
+ throws IOException
+ {
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int numRead = inStr.read(buf, off + totalRead, len - totalRead);
+ if (numRead < 0)
+ {
+ break;
+ }
+ totalRead += numRead;
+ }
+ return totalRead;
+ }
+
+ public static void pipeAll(InputStream inStr, OutputStream outStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ outStr.write(bs, 0, numRead);
+ }
+ }
+
+ public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
+ throws IOException
+ {
+ long total = 0;
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ total += numRead;
+ if (total > limit)
+ {
+ throw new StreamOverflowException("Data Overflow");
+ }
+ outStr.write(bs, 0, numRead);
+ }
+ return total;
+ }
+}
+ * IterableMap map = new HashedMap();
+ * MapIterator it = map.mapIterator();
+ * while (it.hasNext()) {
+ * Object key = it.next();
+ * Object value = it.getValue();
+ * it.setValue("newValue");
+ * }
+ *
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public interface IterableMap extends Map {
+
+ /**
+ * Obtains a MapIterator
over the map.
+ *
+ * IterableMap map = new HashedMap();
+ * MapIterator it = map.mapIterator();
+ * while (it.hasNext()) {
+ * Object key = it.next();
+ * Object value = it.getValue();
+ * it.setValue("newValue");
+ * }
+ *
+ *
+ * @return a map iterator
+ */
+ MapIterator mapIterator();
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/KeyValue.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/KeyValue.java
new file mode 100644
index 00000000..ece1f85c
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/KeyValue.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+/**
+ * Defines a simple key value pair.
+ * Map
.
+ * next()
, the getValue()
method provides direct
+ * access to the value. The value can also be set using setValue()
.
+ *
+ * MapIterator it = map.mapIterator();
+ * while (it.hasNext()) {
+ * Object key = it.next();
+ * Object value = it.getValue();
+ * it.setValue(newValue);
+ * }
+ *
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public interface MapIterator extends Iterator {
+
+ /**
+ * Checks to see if there are more entries still to be iterated.
+ *
+ * @return true
if the iterator has more elements
+ */
+ boolean hasNext();
+
+ /**
+ * Gets the next key from the Map
.
+ *
+ * @return the next key in the iteration
+ * @throws java.util.NoSuchElementException if the iteration is finished
+ */
+ Object next();
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the current key, which is the key returned by the last call
+ * to next()
.
+ *
+ * @return the current key
+ * @throws IllegalStateException if next()
has not yet been called
+ */
+ Object getKey();
+
+ /**
+ * Gets the current value, which is the value associated with the last key
+ * returned by next()
.
+ *
+ * @return the current value
+ * @throws IllegalStateException if next()
has not yet been called
+ */
+ Object getValue();
+
+ //-----------------------------------------------------------------------
+ /**
+ * Removes the last returned key from the underlying Map
(optional operation).
+ * next()
.
+ *
+ * @throws UnsupportedOperationException if remove is not supported by the map
+ * @throws IllegalStateException if next()
has not yet been called
+ * @throws IllegalStateException if remove()
has already been called
+ * since the last call to next()
+ */
+ void remove();
+
+ /**
+ * Sets the value associated with the current key (optional operation).
+ *
+ * @param value the new value
+ * @return the previous value
+ * @throws UnsupportedOperationException if setValue is not supported by the map
+ * @throws IllegalStateException if next()
has not yet been called
+ * @throws IllegalStateException if remove()
has been called since the
+ * last call to next()
+ */
+ Object setValue(Object value);
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/ResettableIterator.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/ResettableIterator.java
new file mode 100644
index 00000000..90c62577
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/ResettableIterator.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections;
+
+import java.util.Iterator;
+
+/**
+ * Defines an iterator that can be reset back to an initial state.
+ * IteratorUtils
.
+ *
+ * @since Commons Collections 2.1.1 and 3.1
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public class EmptyIterator extends AbstractEmptyIterator implements ResettableIterator {
+
+ /**
+ * Singleton instance of the iterator.
+ * @since Commons Collections 3.1
+ */
+ public static final ResettableIterator RESETTABLE_INSTANCE = new EmptyIterator();
+ /**
+ * Singleton instance of the iterator.
+ * @since Commons Collections 2.1.1 and 3.1
+ */
+ public static final Iterator INSTANCE = RESETTABLE_INSTANCE;
+
+ /**
+ * Constructor.
+ */
+ protected EmptyIterator() {
+ super();
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyMapIterator.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyMapIterator.java
new file mode 100644
index 00000000..011ab295
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/iterators/EmptyMapIterator.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.iterators;
+
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.ResettableIterator;
+
+/**
+ * Provides an implementation of an empty map iterator.
+ *
+ * @since Commons Collections 3.1
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Stephen Colebourne
+ */
+public class EmptyMapIterator extends AbstractEmptyIterator implements MapIterator, ResettableIterator {
+
+ /**
+ * Singleton instance of the iterator.
+ * @since Commons Collections 3.1
+ */
+ public static final MapIterator INSTANCE = new EmptyMapIterator();
+
+ /**
+ * Constructor.
+ */
+ protected EmptyMapIterator() {
+ super();
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractKeyValue.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractKeyValue.java
new file mode 100644
index 00000000..02702571
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractKeyValue.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import org.apache.commons.collections.KeyValue;
+
+/**
+ * Abstract pair class to assist with creating KeyValue
+ * and {@link java.util.Map.Entry Map.Entry} implementations.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractKeyValue implements KeyValue {
+
+ /** The key */
+ protected Object key;
+ /** The value */
+ protected Object value;
+
+ /**
+ * Constructs a new pair with the specified key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ protected AbstractKeyValue(Object key, Object value) {
+ super();
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ * Gets the key from the pair.
+ *
+ * @return the key
+ */
+ public Object getKey() {
+ return key;
+ }
+
+ /**
+ * Gets the value from the pair.
+ *
+ * @return the value
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Gets a debugging String view of the pair.
+ *
+ * @return a String view of the entry
+ */
+ public String toString() {
+ return new StringBuffer()
+ .append(getKey())
+ .append('=')
+ .append(getValue())
+ .toString();
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractMapEntry.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractMapEntry.java
new file mode 100644
index 00000000..14e1f9e9
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/keyvalue/AbstractMapEntry.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.keyvalue;
+
+import java.util.Map;
+
+/**
+ * Abstract Pair class to assist with creating correct
+ * {@link java.util.Map.Entry Map.Entry} implementations.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractMapEntry extends AbstractKeyValue implements Map.Entry {
+
+ /**
+ * Constructs a new entry with the given key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ protected AbstractMapEntry(Object key, Object value) {
+ super(key, value);
+ }
+
+ // Map.Entry interface
+ //-------------------------------------------------------------------------
+ /**
+ * Sets the value stored in this Map.Entry
.
+ * Map.Entry
is not connected to a Map, so only the
+ * local data is changed.
+ *
+ * @param value the new value
+ * @return the previous value
+ */
+ public Object setValue(Object value) {
+ Object answer = this.value;
+ this.value = value;
+ return answer;
+ }
+
+ /**
+ * Compares this Map.Entry
with another Map.Entry
.
+ * Map.Entry
contract from being broken.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author James Strachan
+ * @author Michael A. Smith
+ * @author Neil O'Toole
+ * @author Stephen Colebourne
+ */
+public final class DefaultMapEntry extends AbstractMapEntry {
+
+ /**
+ * Constructs a new entry with the specified key and given value.
+ *
+ * @param key the key for the entry, may be null
+ * @param value the value for the entry, may be null
+ */
+ public DefaultMapEntry(final Object key, final Object value) {
+ super(key, value);
+ }
+
+ /**
+ * Constructs a new entry from the specified KeyValue
.
+ *
+ * @param pair the pair to copy, must not be null
+ * @throws NullPointerException if the entry is null
+ */
+ public DefaultMapEntry(final KeyValue pair) {
+ super(pair.getKey(), pair.getValue());
+ }
+
+ /**
+ * Constructs a new entry from the specified Map.Entry
.
+ *
+ * @param entry the entry to copy, must not be null
+ * @throws NullPointerException if the entry is null
+ */
+ public DefaultMapEntry(final Map.Entry entry) {
+ super(entry.getKey(), entry.getValue());
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractHashedMap.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractHashedMap.java
new file mode 100644
index 00000000..1e0e46c2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractHashedMap.java
@@ -0,0 +1,1329 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.map;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.commons.collections.IterableMap;
+import org.apache.commons.collections.KeyValue;
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.EmptyMapIterator;
+
+/**
+ * An abstract implementation of a hash-based map which provides numerous points for
+ * subclasses to override.
+ * HashEntry
class,
+ * which can be overridden and replaced. The iterators can similarly be replaced,
+ * without the need to replace the KeySet, EntrySet and Values view classes.
+ * entry.key
+ * @return true if equal
+ */
+ protected boolean isEqualKey(Object key1, Object key2) {
+ return (key1 == key2 || key1.equals(key2));
+ }
+
+ /**
+ * Compares two values, in external form, to see if they are equal.
+ * This implementation uses the equals method and assumes neither value is null.
+ * Subclasses can override this to match differently.
+ *
+ * @param value1 the first value to compare passed in from outside
+ * @param value2 the second value extracted from the entry via getValue()
+ * @return true if equal
+ */
+ protected boolean isEqualValue(Object value1, Object value2) {
+ return (value1 == value2 || value1.equals(value2));
+ }
+
+ /**
+ * Gets the index into the data storage for the hashCode specified.
+ * This implementation uses the least significant bits of the hashCode.
+ * Subclasses can override this to return alternate bucketing.
+ *
+ * @param hashCode the hash code to use
+ * @param dataSize the size of the data to pick a bucket from
+ * @return the bucket index
+ */
+ protected int hashIndex(int hashCode, int dataSize) {
+ return hashCode & (dataSize - 1);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the entry mapped to the key specified.
+ * setValue()
on the entry.
+ * Subclasses could override to handle changes to the map.
+ *
+ * @param entry the entry to update
+ * @param newValue the new value to store
+ */
+ protected void updateEntry(HashEntry entry, Object newValue) {
+ entry.setValue(newValue);
+ }
+
+ /**
+ * Reuses an existing key-value mapping, storing completely new data.
+ * createEntry()
, addEntry()
+ * and checkCapacity()
.
+ * It also handles changes to modCount
and size
.
+ * Subclasses could override to fully control adds to the map.
+ *
+ * @param hashIndex the index into the data array to store at
+ * @param hashCode the hash code of the key to add
+ * @param key the key to add
+ * @param value the value to add
+ */
+ protected void addMapping(int hashIndex, int hashCode, Object key, Object value) {
+ modCount++;
+ HashEntry entry = createEntry(data[hashIndex], hashCode, key, value);
+ addEntry(entry, hashIndex);
+ size++;
+ checkCapacity();
+ }
+
+ /**
+ * Creates an entry to store the key-value data.
+ * removeEntry()
and destroyEntry()
.
+ * It also handles changes to modCount
and size
.
+ * Subclasses could override to fully control removals from the map.
+ *
+ * @param entry the entry to remove
+ * @param hashIndex the index into the data structure
+ * @param previous the previous entry in the chain
+ */
+ protected void removeMapping(HashEntry entry, int hashIndex, HashEntry previous) {
+ modCount++;
+ removeEntry(entry, hashIndex, previous);
+ size--;
+ destroyEntry(entry);
+ }
+
+ /**
+ * Removes an entry from the chain stored in a particular index.
+ * next
field from a HashEntry
.
+ * Used in subclasses that have no visibility of the field.
+ *
+ * @param entry the entry to query, must not be null
+ * @return the next
field of the entry
+ * @throws NullPointerException if the entry is null
+ * @since Commons Collections 3.1
+ */
+ protected HashEntry entryNext(HashEntry entry) {
+ return entry.next;
+ }
+
+ /**
+ * Gets the hashCode
field from a HashEntry
.
+ * Used in subclasses that have no visibility of the field.
+ *
+ * @param entry the entry to query, must not be null
+ * @return the hashCode
field of the entry
+ * @throws NullPointerException if the entry is null
+ * @since Commons Collections 3.1
+ */
+ protected int entryHashCode(HashEntry entry) {
+ return entry.hashCode;
+ }
+
+ /**
+ * Gets the key
field from a HashEntry
.
+ * Used in subclasses that have no visibility of the field.
+ *
+ * @param entry the entry to query, must not be null
+ * @return the key
field of the entry
+ * @throws NullPointerException if the entry is null
+ * @since Commons Collections 3.1
+ */
+ protected Object entryKey(HashEntry entry) {
+ return entry.key;
+ }
+
+ /**
+ * Gets the value
field from a HashEntry
.
+ * Used in subclasses that have no visibility of the field.
+ *
+ * @param entry the entry to query, must not be null
+ * @return the value
field of the entry
+ * @throws NullPointerException if the entry is null
+ * @since Commons Collections 3.1
+ */
+ protected Object entryValue(HashEntry entry) {
+ return entry.value;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets an iterator over the map.
+ * Changes made to the iterator affect this map.
+ * AbstractHashedMap
but not HashEntry
+ * then you will not be able to access the protected fields.
+ * The entryXxx()
methods on AbstractHashedMap
exist
+ * to provide the necessary access.
+ */
+ protected static class HashEntry implements Map.Entry, KeyValue {
+ /** The next entry in the hash chain */
+ protected HashEntry next;
+ /** The hash code of the key */
+ protected int hashCode;
+ /** The key */
+ protected Object key;
+ /** The value */
+ protected Object value;
+
+ protected HashEntry(HashEntry next, int hashCode, Object key, Object value) {
+ super();
+ this.next = next;
+ this.hashCode = hashCode;
+ this.key = key;
+ this.value = value;
+ }
+
+ public Object getKey() {
+ return (key == NULL ? null : key);
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public Object setValue(Object value) {
+ Object old = this.value;
+ this.value = value;
+ return old;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Map.Entry == false) {
+ return false;
+ }
+ Map.Entry other = (Map.Entry) obj;
+ return
+ (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
+ (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
+ }
+
+ public int hashCode() {
+ return (getKey() == null ? 0 : getKey().hashCode()) ^
+ (getValue() == null ? 0 : getValue().hashCode());
+ }
+
+ public String toString() {
+ return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
+ }
+ }
+
+ /**
+ * Base Iterator
+ */
+ protected static abstract class HashIterator implements Iterator {
+
+ /** The parent map */
+ protected final AbstractHashedMap parent;
+ /** The current index into the array of buckets */
+ protected int hashIndex;
+ /** The last returned entry */
+ protected HashEntry last;
+ /** The next entry */
+ protected HashEntry next;
+ /** The modification count expected */
+ protected int expectedModCount;
+
+ protected HashIterator(AbstractHashedMap parent) {
+ super();
+ this.parent = parent;
+ HashEntry[] data = parent.data;
+ int i = data.length;
+ HashEntry next = null;
+ while (i > 0 && next == null) {
+ next = data[--i];
+ }
+ this.next = next;
+ this.hashIndex = i;
+ this.expectedModCount = parent.modCount;
+ }
+
+ public boolean hasNext() {
+ return (next != null);
+ }
+
+ protected HashEntry nextEntry() {
+ if (parent.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ HashEntry newCurrent = next;
+ if (newCurrent == null) {
+ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
+ }
+ HashEntry[] data = parent.data;
+ int i = hashIndex;
+ HashEntry n = newCurrent.next;
+ while (n == null && i > 0) {
+ n = data[--i];
+ }
+ next = n;
+ hashIndex = i;
+ last = newCurrent;
+ return newCurrent;
+ }
+
+ protected HashEntry currentEntry() {
+ return last;
+ }
+
+ public void remove() {
+ if (last == null) {
+ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
+ }
+ if (parent.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ parent.remove(last.getKey());
+ last = null;
+ expectedModCount = parent.modCount;
+ }
+
+ public String toString() {
+ if (last != null) {
+ return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
+ } else {
+ return "Iterator[]";
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Writes the map data to the stream. This method must be overridden if a
+ * subclass must be setup before put()
is used.
+ * put()
method on read can be
+ * affected by subclass state.
+ * writeObject()
of the first serializable subclass.
+ * put()
is used.
+ * put()
method on read can be
+ * affected by subclass state.
+ * readObject()
of the first serializable subclass.
+ * put()
or calculateThreshold()
will work correctly.
+ *
+ * @param in the input stream
+ */
+ protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ loadFactor = in.readFloat();
+ int capacity = in.readInt();
+ int size = in.readInt();
+ init();
+ threshold = calculateThreshold(capacity, loadFactor);
+ data = new HashEntry[capacity];
+ for (int i = 0; i < size; i++) {
+ Object key = in.readObject();
+ Object value = in.readObject();
+ put(key, value);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Clones the map without cloning the keys or values.
+ * clone()
, a subclass must implement the
+ * Cloneable
interface and make this method public.
+ *
+ * @return a shallow clone
+ */
+ protected Object clone() {
+ try {
+ AbstractHashedMap cloned = (AbstractHashedMap) super.clone();
+ cloned.data = new HashEntry[data.length];
+ cloned.entrySet = null;
+ cloned.keySet = null;
+ cloned.values = null;
+ cloned.modCount = 0;
+ cloned.size = 0;
+ cloned.init();
+ cloned.putAll(this);
+ return cloned;
+
+ } catch (CloneNotSupportedException ex) {
+ return null; // should never happen
+ }
+ }
+
+ /**
+ * Compares this map with another.
+ *
+ * @param obj the object to compare to
+ * @return true if equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Map == false) {
+ return false;
+ }
+ Map map = (Map) obj;
+ if (map.size() != size()) {
+ return false;
+ }
+ MapIterator it = mapIterator();
+ try {
+ while (it.hasNext()) {
+ Object key = it.next();
+ Object value = it.getValue();
+ if (value == null) {
+ if (map.get(key) != null || map.containsKey(key) == false) {
+ return false;
+ }
+ } else {
+ if (value.equals(map.get(key)) == false) {
+ return false;
+ }
+ }
+ }
+ } catch (ClassCastException ignored) {
+ return false;
+ } catch (NullPointerException ignored) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gets the standard Map hashCode.
+ *
+ * @return the hash code defined in the Map interface
+ */
+ public int hashCode() {
+ int total = 0;
+ Iterator it = createEntrySetIterator();
+ while (it.hasNext()) {
+ total += it.next().hashCode();
+ }
+ return total;
+ }
+
+ /**
+ * Gets the map as a String.
+ *
+ * @return a string version of the map
+ */
+ public String toString() {
+ if (size() == 0) {
+ return "{}";
+ }
+ StringBuffer buf = new StringBuffer(32 * size());
+ buf.append('{');
+
+ MapIterator it = mapIterator();
+ boolean hasNext = it.hasNext();
+ while (hasNext) {
+ Object key = it.next();
+ Object value = it.getValue();
+ buf.append(key == this ? "(this Map)" : key)
+ .append('=')
+ .append(value == this ? "(this Map)" : value);
+
+ hasNext = it.hasNext();
+ if (hasNext) {
+ buf.append(',').append(' ');
+ }
+ }
+
+ buf.append('}');
+ return buf.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractReferenceMap.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractReferenceMap.java
new file mode 100644
index 00000000..f11224a2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/AbstractReferenceMap.java
@@ -0,0 +1,981 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.map;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.keyvalue.DefaultMapEntry;
+
+/**
+ * An abstract implementation of a hash-based map that allows the entries to
+ * be removed by the garbage collector.
+ * ReferenceEntry
class which can be overridden and replaced.
+ * The iterators can similarly be replaced, without the need to replace the KeySet,
+ * EntrySet and Values view classes.
+ * AbstractReferenceMap
, you can specify what
+ * kind of references are used to store the map's keys and values.
+ * If non-hard references are used, then the garbage collector can remove
+ * mappings if a key or value becomes unreachable, or if the JVM's memory is
+ * running low. For information on how the different reference types behave,
+ * see {@link Reference}.
+ * WeakHashMap
. However, you can also specify hard keys and
+ * weak values, or any other combination. The default constructor uses
+ * hard keys and soft values, providing a memory-sensitive cache.
+ * NullPointerException
.
+ * ResettableIterator
and calling reset()
.
+ * ReferenceMap
.
+ *
+ * @see java.lang.ref.Reference
+ * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0)
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Paul Jack
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractReferenceMap extends AbstractHashedMap {
+
+ /** Constant indicating that hard references should be used */
+ public static final int HARD = 0;
+
+ /** Constant indicating that soft references should be used */
+ public static final int SOFT = 1;
+
+ /** Constant indicating that weak references should be used */
+ public static final int WEAK = 2;
+
+ /**
+ * The reference type for keys. Must be HARD, SOFT, WEAK.
+ * @serial
+ */
+ protected int keyType;
+
+ /**
+ * The reference type for values. Must be HARD, SOFT, WEAK.
+ * @serial
+ */
+ protected int valueType;
+
+ /**
+ * Should the value be automatically purged when the associated key has been collected?
+ */
+ protected boolean purgeValues;
+
+ /**
+ * ReferenceQueue used to eliminate stale mappings.
+ * See purge.
+ */
+ private transient ReferenceQueue queue;
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructor used during deserialization.
+ */
+ protected AbstractReferenceMap() {
+ super();
+ }
+
+ /**
+ * Constructs a new empty map with the specified reference types,
+ * load factor and initial capacity.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param capacity the initial capacity for the map
+ * @param loadFactor the load factor for the map
+ * @param purgeValues should the value be automatically purged when the
+ * key is garbage collected
+ */
+ protected AbstractReferenceMap(
+ int keyType, int valueType, int capacity,
+ float loadFactor, boolean purgeValues) {
+ super(capacity, loadFactor);
+ verify("keyType", keyType);
+ verify("valueType", valueType);
+ this.keyType = keyType;
+ this.valueType = valueType;
+ this.purgeValues = purgeValues;
+ }
+
+ /**
+ * Initialise this subclass during construction, cloning or deserialization.
+ */
+ protected void init() {
+ queue = new ReferenceQueue();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks the type int is a valid value.
+ *
+ * @param name the name for error messages
+ * @param type the type value to check
+ * @throws IllegalArgumentException if the value if invalid
+ */
+ private static void verify(String name, int type) {
+ if ((type < HARD) || (type > WEAK)) {
+ throw new IllegalArgumentException(name + " must be HARD, SOFT, WEAK.");
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the size of the map.
+ *
+ * @return the size
+ */
+ public int size() {
+ purgeBeforeRead();
+ return super.size();
+ }
+
+ /**
+ * Checks whether the map is currently empty.
+ *
+ * @return true if the map is currently size zero
+ */
+ public boolean isEmpty() {
+ purgeBeforeRead();
+ return super.isEmpty();
+ }
+
+ /**
+ * Checks whether the map contains the specified key.
+ *
+ * @param key the key to search for
+ * @return true if the map contains the key
+ */
+ public boolean containsKey(Object key) {
+ purgeBeforeRead();
+ Entry entry = getEntry(key);
+ if (entry == null) {
+ return false;
+ }
+ return (entry.getValue() != null);
+ }
+
+ /**
+ * Checks whether the map contains the specified value.
+ *
+ * @param value the value to search for
+ * @return true if the map contains the value
+ */
+ public boolean containsValue(Object value) {
+ purgeBeforeRead();
+ if (value == null) {
+ return false;
+ }
+ return super.containsValue(value);
+ }
+
+ /**
+ * Gets the value mapped to the key specified.
+ *
+ * @param key the key
+ * @return the mapped value, null if no match
+ */
+ public Object get(Object key) {
+ purgeBeforeRead();
+ Entry entry = getEntry(key);
+ if (entry == null) {
+ return null;
+ }
+ return entry.getValue();
+ }
+
+
+ /**
+ * Puts a key-value mapping into this map.
+ * Neither the key nor the value may be null.
+ *
+ * @param key the key to add, must not be null
+ * @param value the value to add, must not be null
+ * @return the value previously mapped to this key, null if none
+ * @throws NullPointerException if either the key or value is null
+ */
+ public Object put(Object key, Object value) {
+ if (key == null) {
+ throw new NullPointerException("null keys not allowed");
+ }
+ if (value == null) {
+ throw new NullPointerException("null values not allowed");
+ }
+
+ purgeBeforeWrite();
+ return super.put(key, value);
+ }
+
+ /**
+ * Removes the specified mapping from this map.
+ *
+ * @param key the mapping to remove
+ * @return the value mapped to the removed key, null if key not in map
+ */
+ public Object remove(Object key) {
+ if (key == null) {
+ return null;
+ }
+ purgeBeforeWrite();
+ return super.remove(key);
+ }
+
+ /**
+ * Clears this map.
+ */
+ public void clear() {
+ super.clear();
+ while (queue.poll() != null) {} // drain the queue
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a MapIterator over the reference map.
+ * The iterator only returns valid key/value pairs.
+ *
+ * @return a map iterator
+ */
+ public MapIterator mapIterator() {
+ return new ReferenceMapIterator(this);
+ }
+
+ /**
+ * Returns a set view of this map's entries.
+ * An iterator returned entry is valid until next()
is called again.
+ * The setValue()
method on the toArray
entries has no effect.
+ *
+ * @return a set view of this map's entries
+ */
+ public Set entrySet() {
+ if (entrySet == null) {
+ entrySet = new ReferenceEntrySet(this);
+ }
+ return entrySet;
+ }
+
+ /**
+ * Returns a set view of this map's keys.
+ *
+ * @return a set view of this map's keys
+ */
+ public Set keySet() {
+ if (keySet == null) {
+ keySet = new ReferenceKeySet(this);
+ }
+ return keySet;
+ }
+
+ /**
+ * Returns a collection view of this map's values.
+ *
+ * @return a set view of this map's values
+ */
+ public Collection values() {
+ if (values == null) {
+ values = new ReferenceValues(this);
+ }
+ return values;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Purges stale mappings from this map before read operations.
+ * entry.key
+ * @return true if equal
+ */
+ protected boolean isEqualKey(Object key1, Object key2) {
+ key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
+ return (key1 == key2 || key1.equals(key2));
+ }
+
+ /**
+ * Creates a ReferenceEntry instead of a HashEntry.
+ *
+ * @param next the next entry in sequence
+ * @param hashCode the hash code to use
+ * @param key the key to store
+ * @param value the value to store
+ * @return the newly created entry
+ */
+ protected HashEntry createEntry(HashEntry next, int hashCode, Object key, Object value) {
+ return new ReferenceEntry(this, next, hashCode, key, value);
+ }
+
+ /**
+ * Creates an entry set iterator.
+ *
+ * @return the entrySet iterator
+ */
+ protected Iterator createEntrySetIterator() {
+ return new ReferenceEntrySetIterator(this);
+ }
+
+ /**
+ * Creates an key set iterator.
+ *
+ * @return the keySet iterator
+ */
+ protected Iterator createKeySetIterator() {
+ return new ReferenceKeySetIterator(this);
+ }
+
+ /**
+ * Creates an values iterator.
+ *
+ * @return the values iterator
+ */
+ protected Iterator createValuesIterator() {
+ return new ReferenceValuesIterator(this);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * EntrySet implementation.
+ */
+ static class ReferenceEntrySet extends EntrySet {
+
+ protected ReferenceEntrySet(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] arr) {
+ // special implementation to handle disappearing entries
+ ArrayList list = new ArrayList();
+ Iterator iterator = iterator();
+ while (iterator.hasNext()) {
+ Entry e = (Entry) iterator.next();
+ list.add(new DefaultMapEntry(e.getKey(), e.getValue()));
+ }
+ return list.toArray(arr);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * KeySet implementation.
+ */
+ static class ReferenceKeySet extends KeySet {
+
+ protected ReferenceKeySet(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] arr) {
+ // special implementation to handle disappearing keys
+ List list = new ArrayList(parent.size());
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ list.add(it.next());
+ }
+ return list.toArray(arr);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Values implementation.
+ */
+ static class ReferenceValues extends Values {
+
+ protected ReferenceValues(AbstractHashedMap parent) {
+ super(parent);
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[0]);
+ }
+
+ public Object[] toArray(Object[] arr) {
+ // special implementation to handle disappearing values
+ List list = new ArrayList(parent.size());
+ for (Iterator it = iterator(); it.hasNext(); ) {
+ list.add(it.next());
+ }
+ return list.toArray(arr);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * A MapEntry implementation for the map.
+ * isEqualKey
and
+ * isEqualValue
on the main map for comparison.
+ *
+ * @param obj the other map entry to compare to
+ * @return true if equal, false if not
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Map.Entry == false) {
+ return false;
+ }
+
+ Map.Entry entry = (Map.Entry)obj;
+ Object entryKey = entry.getKey(); // convert to hard reference
+ Object entryValue = entry.getValue(); // convert to hard reference
+ if ((entryKey == null) || (entryValue == null)) {
+ return false;
+ }
+ // compare using map methods, aiding identity subclass
+ // note that key is direct access and value is via method
+ return parent.isEqualKey(entryKey, key) &&
+ parent.isEqualValue(entryValue, getValue());
+ }
+
+ /**
+ * Gets the hashcode of the entry using temporary hard references.
+ * hashEntry
on the main map.
+ *
+ * @return the hashcode of the entry
+ */
+ public int hashCode() {
+ return parent.hashEntry(getKey(), getValue());
+ }
+
+ /**
+ * Constructs a reference of the given type to the given referent.
+ * The reference is registered with the queue for later purging.
+ *
+ * @param type HARD, SOFT or WEAK
+ * @param referent the object to refer to
+ * @param hash the hash code of the key of the mapping;
+ * this number might be different from referent.hashCode() if
+ * the referent represents a value and not a key
+ */
+ protected Object toReference(int type, Object referent, int hash) {
+ switch (type) {
+ case HARD: return referent;
+ case SOFT: return new SoftRef(hash, referent, parent.queue);
+ case WEAK: return new WeakRef(hash, referent, parent.queue);
+ default: throw new Error();
+ }
+ }
+
+ /**
+ * Purges the specified reference
+ * @param ref the reference to purge
+ * @return true or false
+ */
+ boolean purge(Reference ref) {
+ boolean r = (parent.keyType > HARD) && (key == ref);
+ r = r || ((parent.valueType > HARD) && (value == ref));
+ if (r) {
+ if (parent.keyType > HARD) {
+ ((Reference)key).clear();
+ }
+ if (parent.valueType > HARD) {
+ ((Reference)value).clear();
+ } else if (parent.purgeValues) {
+ value = null;
+ }
+ }
+ return r;
+ }
+
+ /**
+ * Gets the next entry in the bucket.
+ *
+ * @return the next entry in the bucket
+ */
+ protected ReferenceEntry next() {
+ return (ReferenceEntry) next;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * The EntrySet iterator.
+ */
+ static class ReferenceEntrySetIterator implements Iterator {
+ /** The parent map */
+ final AbstractReferenceMap parent;
+
+ // These fields keep track of where we are in the table.
+ int index;
+ ReferenceEntry entry;
+ ReferenceEntry previous;
+
+ // These Object fields provide hard references to the
+ // current and next entry; this assures that if hasNext()
+ // returns true, next() will actually return a valid element.
+ Object nextKey, nextValue;
+ Object currentKey, currentValue;
+
+ int expectedModCount;
+
+ public ReferenceEntrySetIterator(AbstractReferenceMap parent) {
+ super();
+ this.parent = parent;
+ index = (parent.size() != 0 ? parent.data.length : 0);
+ // have to do this here! size() invocation above
+ // may have altered the modCount.
+ expectedModCount = parent.modCount;
+ }
+
+ public boolean hasNext() {
+ checkMod();
+ while (nextNull()) {
+ ReferenceEntry e = entry;
+ int i = index;
+ while ((e == null) && (i > 0)) {
+ i--;
+ e = (ReferenceEntry) parent.data[i];
+ }
+ entry = e;
+ index = i;
+ if (e == null) {
+ currentKey = null;
+ currentValue = null;
+ return false;
+ }
+ nextKey = e.getKey();
+ nextValue = e.getValue();
+ if (nextNull()) {
+ entry = entry.next();
+ }
+ }
+ return true;
+ }
+
+ private void checkMod() {
+ if (parent.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private boolean nextNull() {
+ return (nextKey == null) || (nextValue == null);
+ }
+
+ protected ReferenceEntry nextEntry() {
+ checkMod();
+ if (nextNull() && !hasNext()) {
+ throw new NoSuchElementException();
+ }
+ previous = entry;
+ entry = entry.next();
+ currentKey = nextKey;
+ currentValue = nextValue;
+ nextKey = null;
+ nextValue = null;
+ return previous;
+ }
+
+ protected ReferenceEntry currentEntry() {
+ checkMod();
+ return previous;
+ }
+
+ public Object next() {
+ return nextEntry();
+ }
+
+ public void remove() {
+ checkMod();
+ if (previous == null) {
+ throw new IllegalStateException();
+ }
+ parent.remove(currentKey);
+ previous = null;
+ currentKey = null;
+ currentValue = null;
+ expectedModCount = parent.modCount;
+ }
+ }
+
+ /**
+ * The keySet iterator.
+ */
+ static class ReferenceKeySetIterator extends ReferenceEntrySetIterator {
+
+ ReferenceKeySetIterator(AbstractReferenceMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return nextEntry().getKey();
+ }
+ }
+
+ /**
+ * The values iterator.
+ */
+ static class ReferenceValuesIterator extends ReferenceEntrySetIterator {
+
+ ReferenceValuesIterator(AbstractReferenceMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return nextEntry().getValue();
+ }
+ }
+
+ /**
+ * The MapIterator implementation.
+ */
+ static class ReferenceMapIterator extends ReferenceEntrySetIterator implements MapIterator {
+
+ protected ReferenceMapIterator(AbstractReferenceMap parent) {
+ super(parent);
+ }
+
+ public Object next() {
+ return nextEntry().getKey();
+ }
+
+ public Object getKey() {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
+ }
+ return current.getKey();
+ }
+
+ public Object getValue() {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
+ }
+ return current.getValue();
+ }
+
+ public Object setValue(Object value) {
+ HashEntry current = currentEntry();
+ if (current == null) {
+ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
+ }
+ return current.setValue(value);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ // These two classes store the hashCode of the key of
+ // of the mapping, so that after they're dequeued a quick
+ // lookup of the bucket in the table can occur.
+
+ /**
+ * A soft reference holder.
+ */
+ static class SoftRef extends SoftReference {
+ /** the hashCode of the key (even if the reference points to a value) */
+ private int hash;
+
+ public SoftRef(int hash, Object r, ReferenceQueue q) {
+ super(r, q);
+ this.hash = hash;
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+ }
+
+ /**
+ * A weak reference holder.
+ */
+ static class WeakRef extends WeakReference {
+ /** the hashCode of the key (even if the reference points to a value) */
+ private int hash;
+
+ public WeakRef(int hash, Object r, ReferenceQueue q) {
+ super(r, q);
+ this.hash = hash;
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces the superclass method to store the state of this class.
+ * put()
method on read can be
+ * affected by subclass state.
+ * writeObject()
of the first serializable subclass.
+ * put()
method on read can be
+ * affected by subclass state.
+ * readObject()
of the first serializable subclass.
+ * put()
or calculateThreshold()
will work correctly.
+ *
+ * @param in the input stream
+ */
+ protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ this.keyType = in.readInt();
+ this.valueType = in.readInt();
+ this.purgeValues = in.readBoolean();
+ this.loadFactor = in.readFloat();
+ int capacity = in.readInt();
+ init();
+ data = new HashEntry[capacity];
+ while (true) {
+ Object key = in.readObject();
+ if (key == null) {
+ break;
+ }
+ Object value = in.readObject();
+ put(key, value);
+ }
+ threshold = calculateThreshold(data.length, loadFactor);
+ // do not call super.doReadObject() as code there doesn't work for reference map
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/ReferenceMap.java b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/ReferenceMap.java
new file mode 100644
index 00000000..fa057997
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/apache/commons/collections/map/ReferenceMap.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.collections.map;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * A Map
implementation that allows mappings to be
+ * removed by the garbage collector.
+ * ReferenceMap
, you can specify what kind
+ * of references are used to store the map's keys and values.
+ * If non-hard references are used, then the garbage collector can remove
+ * mappings if a key or value becomes unreachable, or if the JVM's memory is
+ * running low. For information on how the different reference types behave,
+ * see {@link java.lang.ref.Reference Reference}.
+ * WeakHashMap
. However, you can also specify hard keys and
+ * weak values, or any other combination. The default constructor uses
+ * hard keys and soft values, providing a memory-sensitive cache.
+ * equals()
.
+ * NullPointerException
.
+ * ReferenceMap
.
+ * Remember that synchronization will not stop the garbage collecter removing entries.
+ * ResettableIterator
and calling reset()
.
+ * AbstractReferenceMap
+ * (previously it extended AbstractMap). As a result, the implementation is now
+ * extensible and provides a MapIterator
.
+ *
+ * @see java.lang.ref.Reference
+ *
+ * @since Commons Collections 3.0 (previously in main package v2.1)
+ * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
+ *
+ * @author Paul Jack
+ * @author Stephen Colebourne
+ */
+public class ReferenceMap extends AbstractReferenceMap implements Serializable {
+
+ /** Serialization version */
+ private static final long serialVersionUID = 1555089888138299607L;
+
+ /**
+ * Constructs a new ReferenceMap
that will
+ * use hard references to keys and soft references to values.
+ */
+ public ReferenceMap() {
+ super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
+ }
+
+ /**
+ * Constructs a new ReferenceMap
that will
+ * use the specified types of references.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ */
+ public ReferenceMap(int keyType, int valueType) {
+ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
+ }
+
+ /**
+ * Constructs a new ReferenceMap
that will
+ * use the specified types of references.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param purgeValues should the value be automatically purged when the
+ * key is garbage collected
+ */
+ public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
+ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
+ }
+
+ /**
+ * Constructs a new ReferenceMap
with the
+ * specified reference types, load factor and initial
+ * capacity.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param capacity the initial capacity for the map
+ * @param loadFactor the load factor for the map
+ */
+ public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) {
+ super(keyType, valueType, capacity, loadFactor, false);
+ }
+
+ /**
+ * Constructs a new ReferenceMap
with the
+ * specified reference types, load factor and initial
+ * capacity.
+ *
+ * @param keyType the type of reference to use for keys;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param valueType the type of reference to use for values;
+ * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
+ * @param capacity the initial capacity for the map
+ * @param loadFactor the load factor for the map
+ * @param purgeValues should the value be automatically purged when the
+ * key is garbage collected
+ */
+ public ReferenceMap(int keyType, int valueType, int capacity,
+ float loadFactor, boolean purgeValues) {
+ super(keyType, valueType, capacity, loadFactor, purgeValues);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Write the map out using a custom routine.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ doWriteObject(out);
+ }
+
+ /**
+ * Read the map in using a custom routine.
+ */
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ doReadObject(in);
+ }
+
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
new file mode 100644
index 00000000..83bc39d2
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
@@ -0,0 +1,10 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1ApplicationSpecificParser
+ extends DEREncodable
+{
+ DEREncodable readObject()
+ throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Choice.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Choice.java
new file mode 100644
index 00000000..603131d1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/ASN1Choice.java
@@ -0,0 +1,14 @@
+package org.bouncycastle.asn1;
+
+/**
+ * Marker interface for CHOICE objects - if you implement this in a role your
+ * own object any attempt to tag the object implicitly will convert the tag to
+ * an explicit one as the encoding rules require.
+ * null
if not set.
+ * @param indirectReference The indirect reference or null
if not set.
+ * @param dataValueDescriptor The data value descriptor or null
if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, DERTaggedObject externalData)
+ {
+ this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.getDERObject());
+ }
+
+ /**
+ * Creates a new instance of DERExternal.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or null
if not set.
+ * @param indirectReference The indirect reference or null
if not set.
+ * @param dataValueDescriptor The data value descriptor or null
if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, int encoding, DERObject externalData)
+ {
+ setDirectReference(directReference);
+ setIndirectReference(indirectReference);
+ setDataValueDescriptor(dataValueDescriptor);
+ setEncoding(encoding);
+ setExternalContent(externalData.getDERObject());
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ int ret = 0;
+ if (directReference != null)
+ {
+ ret = directReference.hashCode();
+ }
+ if (indirectReference != null)
+ {
+ ret ^= indirectReference.hashCode();
+ }
+ if (dataValueDescriptor != null)
+ {
+ ret ^= dataValueDescriptor.hashCode();
+ }
+ ret ^= externalContent.hashCode();
+ return ret;
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(DEROutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ if (directReference != null)
+ {
+ baos.write(directReference.getDEREncoded());
+ }
+ if (indirectReference != null)
+ {
+ baos.write(indirectReference.getDEREncoded());
+ }
+ if (dataValueDescriptor != null)
+ {
+ baos.write(dataValueDescriptor.getDEREncoded());
+ }
+ DERTaggedObject obj = new DERTaggedObject(encoding, externalContent);
+ baos.write(obj.getDEREncoded());
+ out.writeEncoded(DERTags.CONSTRUCTED, DERTags.EXTERNAL, baos.toByteArray());
+ }
+
+ /* (non-Javadoc)
+ * @see org.bouncycastle.asn1.ASN1Object#asn1Equals(org.bouncycastle.asn1.DERObject)
+ */
+ boolean asn1Equals(DERObject o)
+ {
+ if (!(o instanceof DERExternal))
+ {
+ return false;
+ }
+ if (this == o)
+ {
+ return true;
+ }
+ DERExternal other = (DERExternal)o;
+ if (directReference != null)
+ {
+ if (other.directReference == null || !other.directReference.equals(directReference))
+ {
+ return false;
+ }
+ }
+ if (indirectReference != null)
+ {
+ if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
+ {
+ return false;
+ }
+ }
+ if (dataValueDescriptor != null)
+ {
+ if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
+ {
+ return false;
+ }
+ }
+ return externalContent.equals(other.externalContent);
+ }
+
+ /**
+ * Returns the data value descriptor
+ * @return The descriptor
+ */
+ public ASN1Object getDataValueDescriptor()
+ {
+ return dataValueDescriptor;
+ }
+
+ /**
+ * Returns the direct reference of the external element
+ * @return The reference
+ */
+ public DERObjectIdentifier getDirectReference()
+ {
+ return directReference;
+ }
+
+ /**
+ * Returns the encoding of the content. Valid values are
+ *
+ *
+ * @return The encoding
+ */
+ public int getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Returns the content of this element
+ * @return The content
+ */
+ public DERObject getExternalContent()
+ {
+ return externalContent;
+ }
+
+ /**
+ * Returns the indirect reference of this element
+ * @return The reference
+ */
+ public DERInteger getIndirectReference()
+ {
+ return indirectReference;
+ }
+
+ /**
+ * Sets the data value descriptor
+ * @param dataValueDescriptor The descriptor
+ */
+ private void setDataValueDescriptor(ASN1Object dataValueDescriptor)
+ {
+ this.dataValueDescriptor = dataValueDescriptor;
+ }
+
+ /**
+ * Sets the direct reference of the external element
+ * @param directReferemce The reference
+ */
+ private void setDirectReference(DERObjectIdentifier directReferemce)
+ {
+ this.directReference = directReferemce;
+ }
+
+ /**
+ * Sets the encoding of the content. Valid values are
+ * 0
single-ASN1-type1
OCTET STRING2
BIT STRING
+ *
+ * @param encoding The encoding
+ */
+ private void setEncoding(int encoding)
+ {
+ if (encoding < 0 || encoding > 2)
+ {
+ throw new IllegalArgumentException("invalid encoding value: " + encoding);
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Sets the content of this element
+ * @param externalContent The content
+ */
+ private void setExternalContent(DERObject externalContent)
+ {
+ this.externalContent = externalContent;
+ }
+
+ /**
+ * Sets the indirect reference of this element
+ * @param indirectReference The reference
+ */
+ private void setIndirectReference(DERInteger indirectReference)
+ {
+ this.indirectReference = indirectReference;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternalParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternalParser.java
new file mode 100644
index 00000000..0fbfb680
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERExternalParser.java
@@ -0,0 +1,39 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERExternalParser
+ implements DEREncodable
+{
+ private ASN1StreamParser _parser;
+
+ /**
+ *
+ */
+ public DERExternalParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public DEREncodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new DERExternal(_parser.readVector());
+ }
+ catch (IOException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ catch (IllegalArgumentException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERFactory.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERFactory.java
new file mode 100644
index 00000000..7364282e
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERFactory.java
@@ -0,0 +1,22 @@
+package org.bouncycastle.asn1;
+
+class DERFactory
+{
+ static final DERSequence EMPTY_SEQUENCE = new DERSequence();
+ static final DERSet EMPTY_SET = new DERSet();
+
+ static DERSequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new DERSequence(v);
+ }
+
+ static DERSet createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new DERSet(v);
+ }
+
+ static DERSet createSet(ASN1EncodableVector v, boolean needsSorting)
+ {
+ return v.size() < 1 ? EMPTY_SET : new DERSet(v, needsSorting);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralString.java
new file mode 100644
index 00000000..1992cf34
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralString.java
@@ -0,0 +1,92 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERGeneralString
+ extends ASN1Object implements DERString
+{
+ private String string;
+
+ public static DERGeneralString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERGeneralString)
+ {
+ return (DERGeneralString) obj;
+ }
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERGeneralString(((ASN1OctetString) obj).getOctets());
+ }
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject) obj).getObject());
+ }
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static DERGeneralString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public DERGeneralString(byte[] string)
+ {
+ char[] cs = new char[string.length];
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+ this.string = new String(cs);
+ }
+
+ public DERGeneralString(String string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte) cs[i];
+ }
+ return bs;
+ }
+
+ void encode(DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(GENERAL_STRING, this.getOctets());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ boolean asn1Equals(DERObject o)
+ {
+ if (!(o instanceof DERGeneralString))
+ {
+ return false;
+ }
+ DERGeneralString s = (DERGeneralString) o;
+ return this.getString().equals(s.getString());
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralizedTime.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralizedTime.java
new file mode 100644
index 00000000..53663478
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGeneralizedTime.java
@@ -0,0 +1,314 @@
+package org.bouncycastle.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;
+
+/**
+ * Generalized time object.
+ */
+public class DERGeneralizedTime
+ extends ASN1Object
+{
+ String time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERGeneralizedTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERGeneralizedTime)
+ {
+ return (DERGeneralizedTime)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * 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 DERGeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * 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 = time;
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructer from a java.util.date object
+ */
+ public DERGeneralizedTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = dateF.format(time);
+ }
+
+ DERGeneralizedTime(
+ byte[] bytes)
+ {
+ //
+ // explicitly convert to characters
+ //
+ char[] dateC = new char[bytes.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)(bytes[i] & 0xff);
+ }
+
+ this.time = new String(dateC);
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return time;
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * 0
single-ASN1-type1
OCTET STRING2
BIT STRING
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ //
+ // standardise the format.
+ //
+ if (time.charAt(time.length() - 1) == 'Z')
+ {
+ return time.substring(0, time.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = time.length() - 5;
+ char sign = time.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return time.substring(0, signPos)
+ + "GMT"
+ + time.substring(signPos, signPos + 3)
+ + ":"
+ + time.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = time.length() - 3;
+ sign = time.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return time.substring(0, signPos)
+ + "GMT"
+ + time.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return time + 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 d = time;
+
+ if (time.endsWith("Z"))
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else if (time.indexOf('-') > 0 || time.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;
+ }
+ }
+
+ return dateF.parse(d);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ return time.indexOf('.') == 14;
+ }
+
+ private byte[] getOctets()
+ {
+ char[] cs = time.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(GENERALIZED_TIME, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERGeneralizedTime))
+ {
+ return false;
+ }
+
+ return time.equals(((DERGeneralizedTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return time.hashCode();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGenerator.java
new file mode 100644
index 00000000..8aef7a74
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERGenerator.java
@@ -0,0 +1,119 @@
+package org.bouncycastle.asn1;
+
+import org.bouncycastle.util.io.Streams;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public abstract class DERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected DERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public DERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ private void writeLength(
+ OutputStream out,
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ out.write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ out.write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ out.write((byte)length);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ out.write(tag);
+ writeLength(out, bytes.length);
+ out.write(bytes);
+ }
+
+ void writeDEREncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | DERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ writeDEREncoded(bOut, tag, bytes);
+
+ writeDEREncoded(_out, newTag, bOut.toByteArray());
+ }
+ else
+ {
+ if ((tag & DERTags.CONSTRUCTED) != 0)
+ {
+ writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
+ }
+ else
+ {
+ writeDEREncoded(_out, tagNum, bytes);
+ }
+ }
+ }
+ else
+ {
+ writeDEREncoded(_out, tag, bytes);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ InputStream in)
+ throws IOException
+ {
+ writeDEREncoded(out, tag, Streams.readAll(in));
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERIA5String.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERIA5String.java
new file mode 100644
index 00000000..a90830c1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERIA5String.java
@@ -0,0 +1,174 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER IA5String object - this is an ascii string.
+ */
+public class DERIA5String
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a IA5 string from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERIA5String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERIA5String)
+ {
+ return (DERIA5String)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERIA5String(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an IA5 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.
+ */
+ public static DERIA5String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DERIA5String(
+ byte[] string)
+ {
+ char[] cs = new char[string.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor - without validation.
+ */
+ public DERIA5String(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in an IA5String.
+ */
+ public DERIA5String(
+ String string,
+ boolean validate)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ if (validate && !isIA5String(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(IA5_STRING, this.getOctets());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERIA5String))
+ {
+ return false;
+ }
+
+ DERIA5String s = (DERIA5String)o;
+
+ return this.getString().equals(s.getString());
+ }
+
+ /**
+ * 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.
+ */
+ public static boolean isIA5String(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInputStream.java
new file mode 100644
index 00000000..51f55055
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInputStream.java
@@ -0,0 +1,272 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Don't use this class. It will eventually disappear, use ASN1InputStream.
+ *
+ * This class is scheduled for removal.
+ * @deprecated use ASN1InputStream
+ */
+public class DERInputStream
+ extends FilterInputStream implements DERTags
+{
+ /**
+ * @deprecated use ASN1InputStream
+ */
+ public DERInputStream(
+ InputStream is)
+ {
+ super(is);
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ int length = read();
+ if (length < 0)
+ {
+ throw new IOException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes");
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = read();
+
+ if (next < 0)
+ {
+ throw new IOException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+ }
+
+ return length;
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ int left = bytes.length;
+
+ if (left == 0)
+ {
+ return;
+ }
+
+ while (left > 0)
+ {
+ int l = read(bytes, bytes.length - left, left);
+
+ if (l < 0)
+ {
+ throw new EOFException("unexpected end of stream");
+ }
+
+ left -= l;
+ }
+ }
+
+ /**
+ * build an object given its tag and a byte stream to construct it
+ * from.
+ */
+ protected DERObject buildObject(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ switch (tag)
+ {
+ case NULL:
+ return null;
+ case SEQUENCE | CONSTRUCTED:
+ ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
+ BERInputStream dIn = new BERInputStream(bIn);
+ DERConstructedSequence seq = new DERConstructedSequence();
+
+ try
+ {
+ for (;;)
+ {
+ DERObject obj = dIn.readObject();
+
+ seq.addObject(obj);
+ }
+ }
+ catch (EOFException ex)
+ {
+ return seq;
+ }
+ case SET | CONSTRUCTED:
+ bIn = new ByteArrayInputStream(bytes);
+ dIn = new BERInputStream(bIn);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ try
+ {
+ for (;;)
+ {
+ DERObject obj = dIn.readObject();
+
+ v.add(obj);
+ }
+ }
+ catch (EOFException ex)
+ {
+ return new DERConstructedSet(v);
+ }
+ case BOOLEAN:
+ return new DERBoolean(bytes);
+ case INTEGER:
+ return new DERInteger(bytes);
+ case ENUMERATED:
+ return new DEREnumerated(bytes);
+ case OBJECT_IDENTIFIER:
+ return new DERObjectIdentifier(bytes);
+ case BIT_STRING:
+ int padBits = bytes[0];
+ byte[] data = new byte[bytes.length - 1];
+
+ System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+
+ return new DERBitString(data, padBits);
+ case UTF8_STRING:
+ return new DERUTF8String(bytes);
+ case PRINTABLE_STRING:
+ return new DERPrintableString(bytes);
+ case IA5_STRING:
+ return new DERIA5String(bytes);
+ case T61_STRING:
+ return new DERT61String(bytes);
+ case VISIBLE_STRING:
+ return new DERVisibleString(bytes);
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(bytes);
+ case GENERAL_STRING:
+ return new DERGeneralString(bytes);
+ case BMP_STRING:
+ return new DERBMPString(bytes);
+ case OCTET_STRING:
+ return new DEROctetString(bytes);
+ case UTC_TIME:
+ return new DERUTCTime(bytes);
+ case GENERALIZED_TIME:
+ return new DERGeneralizedTime(bytes);
+ default:
+ //
+ // with tagged object tag number is bottom 5 bits
+ //
+ if ((tag & TAGGED) != 0)
+ {
+ if ((tag & 0x1f) == 0x1f)
+ {
+ throw new IOException("unsupported high tag encountered");
+ }
+
+ if (bytes.length == 0) // empty tag!
+ {
+ if ((tag & CONSTRUCTED) == 0)
+ {
+ return new DERTaggedObject(false, tag & 0x1f, new DERNull());
+ }
+ else
+ {
+ return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
+ }
+ }
+
+ //
+ // simple type - implicit... return an octet string
+ //
+ if ((tag & CONSTRUCTED) == 0)
+ {
+ return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
+ }
+
+ bIn = new ByteArrayInputStream(bytes);
+ dIn = new BERInputStream(bIn);
+
+ DEREncodable dObj = dIn.readObject();
+
+ //
+ // explicitly tagged (probably!) - if it isn't we'd have to
+ // tell from the context
+ //
+ if (dIn.available() == 0)
+ {
+ return new DERTaggedObject(tag & 0x1f, dObj);
+ }
+
+ //
+ // another implicit object, we'll create a sequence...
+ //
+ seq = new DERConstructedSequence();
+
+ seq.addObject(dObj);
+
+ try
+ {
+ for (;;)
+ {
+ dObj = dIn.readObject();
+
+ seq.addObject(dObj);
+ }
+ }
+ catch (EOFException ex)
+ {
+ // ignore --
+ }
+
+ return new DERTaggedObject(false, tag & 0x1f, seq);
+ }
+
+ return new DERUnknownTag(tag, bytes);
+ }
+ }
+
+ public DERObject readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag == -1)
+ {
+ throw new EOFException();
+ }
+
+ int length = readLength();
+ byte[] bytes = new byte[length];
+
+ readFully(bytes);
+
+ return buildObject(tag, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInteger.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInteger.java
new file mode 100644
index 00000000..8f97428b
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERInteger.java
@@ -0,0 +1,123 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import org.bouncycastle.util.Arrays;
+
+public class DERInteger
+ extends ASN1Object
+{
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERInteger getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERInteger)
+ {
+ return (DERInteger)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERInteger(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * 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 DERInteger getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public DERInteger(
+ int value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ public DERInteger(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ 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);
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(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(
+ DERObject o)
+ {
+ if (!(o instanceof DERInteger))
+ {
+ return false;
+ }
+
+ DERInteger other = (DERInteger)o;
+
+ return Arrays.areEqual(bytes, other.bytes);
+ }
+
+ public String toString()
+ {
+ return getValue().toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNull.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNull.java
new file mode 100644
index 00000000..5d020c7d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNull.java
@@ -0,0 +1,25 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object.
+ */
+public class DERNull
+ extends ASN1Null
+{
+ public static final DERNull INSTANCE = new DERNull();
+
+ byte[] zeroBytes = new byte[0];
+
+ public DERNull()
+ {
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(NULL, zeroBytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNumericString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNumericString.java
new file mode 100644
index 00000000..3c721936
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERNumericString.java
@@ -0,0 +1,177 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+ */
+public class DERNumericString
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a Numeric string from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERNumericString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERNumericString)
+ {
+ return (DERNumericString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERNumericString(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Numeric 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.
+ */
+ public static DERNumericString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DERNumericString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor - without validation..
+ */
+ public DERNumericString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a NumericString.
+ */
+ public DERNumericString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isNumericString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(NUMERIC_STRING, this.getOctets());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERNumericString))
+ {
+ return false;
+ }
+
+ DERNumericString s = (DERNumericString)o;
+
+ return this.getString().equals(s.getString());
+ }
+
+ /**
+ * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+ *
+ * @param str string to validate.
+ * @return true if numeric, fale otherwise.
+ */
+ public static boolean isNumericString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if (('0' <= ch && ch <= '9') || ch == ' ')
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObject.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObject.java
new file mode 100644
index 00000000..42e24878
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObject.java
@@ -0,0 +1,20 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public abstract class DERObject
+ extends ASN1Encodable
+ implements DERTags
+{
+ public DERObject toASN1Object()
+ {
+ return this;
+ }
+
+ public abstract int hashCode();
+
+ public abstract boolean equals(Object o);
+
+ abstract void encode(DEROutputStream out)
+ throws IOException;
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObjectIdentifier.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObjectIdentifier.java
new file mode 100644
index 00000000..1ba6b2d1
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERObjectIdentifier.java
@@ -0,0 +1,293 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+public class DERObjectIdentifier
+ extends ASN1Object
+{
+ String identifier;
+
+ /**
+ * return an OID from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERObjectIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERObjectIdentifier)
+ {
+ return (DERObjectIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERObjectIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+
+ DERObjectIdentifier(
+ byte[] bytes)
+ {
+ StringBuffer objId = new StringBuffer();
+ long value = 0;
+ BigInteger bigValue = null;
+ boolean first = true;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ int b = bytes[i] & 0xff;
+
+ if (value < 0x80000000000000L)
+ {
+ value = value * 128 + (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ switch ((int)value / 40)
+ {
+ case 0:
+ objId.append('0');
+ break;
+ case 1:
+ objId.append('1');
+ value -= 40;
+ break;
+ default:
+ objId.append('2');
+ value -= 80;
+ }
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(value);
+ value = 0;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.valueOf(value);
+ }
+ bigValue = bigValue.shiftLeft(7);
+ bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ objId.append('.');
+ objId.append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ }
+ }
+
+ this.identifier = objId.toString();
+ }
+
+ public DERObjectIdentifier(
+ String identifier)
+ {
+ if (!isValidIdentifier(identifier))
+ {
+ throw new IllegalArgumentException("string " + identifier + " not an OID");
+ }
+
+ this.identifier = identifier;
+ }
+
+ public String getId()
+ {
+ return identifier;
+ }
+
+ private void writeField(
+ OutputStream out,
+ long fieldValue)
+ throws IOException
+ {
+ if (fieldValue >= (1L << 7))
+ {
+ if (fieldValue >= (1L << 14))
+ {
+ if (fieldValue >= (1L << 21))
+ {
+ if (fieldValue >= (1L << 28))
+ {
+ if (fieldValue >= (1L << 35))
+ {
+ if (fieldValue >= (1L << 42))
+ {
+ if (fieldValue >= (1L << 49))
+ {
+ if (fieldValue >= (1L << 56))
+ {
+ out.write((int)(fieldValue >> 56) | 0x80);
+ }
+ out.write((int)(fieldValue >> 49) | 0x80);
+ }
+ out.write((int)(fieldValue >> 42) | 0x80);
+ }
+ out.write((int)(fieldValue >> 35) | 0x80);
+ }
+ out.write((int)(fieldValue >> 28) | 0x80);
+ }
+ out.write((int)(fieldValue >> 21) | 0x80);
+ }
+ out.write((int)(fieldValue >> 14) | 0x80);
+ }
+ out.write((int)(fieldValue >> 7) | 0x80);
+ }
+ out.write((int)fieldValue & 0x7f);
+ }
+
+ private void writeField(
+ OutputStream out,
+ BigInteger fieldValue)
+ throws IOException
+ {
+ 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);
+ }
+
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ OIDTokenizer tok = new OIDTokenizer(identifier);
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ writeField(bOut,
+ Integer.parseInt(tok.nextToken()) * 40
+ + Integer.parseInt(tok.nextToken()));
+
+ while (tok.hasMoreTokens())
+ {
+ String token = tok.nextToken();
+ if (token.length() < 18)
+ {
+ writeField(bOut, Long.parseLong(token));
+ }
+ else
+ {
+ writeField(bOut, new BigInteger(token));
+ }
+ }
+
+ dOut.close();
+
+ byte[] bytes = bOut.toByteArray();
+
+ out.writeEncoded(OBJECT_IDENTIFIER, bytes);
+ }
+
+ public int hashCode()
+ {
+ return identifier.hashCode();
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERObjectIdentifier))
+ {
+ return false;
+ }
+
+ return identifier.equals(((DERObjectIdentifier)o).identifier);
+ }
+
+ public String toString()
+ {
+ return getId();
+ }
+
+ 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;
+ }
+
+ boolean periodAllowed = false;
+ for (int i = identifier.length() - 1; i >= 2; i--)
+ {
+ char ch = identifier.charAt(i);
+
+ if ('0' <= ch && ch <= '9')
+ {
+ periodAllowed = true;
+ continue;
+ }
+
+ if (ch == '.')
+ {
+ if (!periodAllowed)
+ {
+ return false;
+ }
+
+ periodAllowed = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return periodAllowed;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetString.java
new file mode 100644
index 00000000..cadd60c8
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetString.java
@@ -0,0 +1,37 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DEROctetString
+ extends ASN1OctetString
+{
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public DEROctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public DEROctetString(
+ DEREncodable obj)
+ {
+ super(obj);
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(OCTET_STRING, string);
+ }
+
+ static void encode(
+ DEROutputStream derOut,
+ byte[] bytes)
+ throws IOException
+ {
+ derOut.writeEncoded(DERTags.OCTET_STRING, bytes);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetStringParser.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetStringParser.java
new file mode 100644
index 00000000..f6138d97
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROctetStringParser.java
@@ -0,0 +1,33 @@
+package org.bouncycastle.asn1;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+public class DEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private DefiniteLengthInputStream stream;
+
+ DEROctetStringParser(
+ DefiniteLengthInputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return stream;
+ }
+
+ public DERObject getDERObject()
+ {
+ try
+ {
+ return new DEROctetString(stream.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROutputStream.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROutputStream.java
new file mode 100644
index 00000000..b78f7caf
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DEROutputStream.java
@@ -0,0 +1,134 @@
+package org.bouncycastle.asn1;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DEROutputStream
+ extends FilterOutputStream implements DERTags
+{
+ public DEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ private void writeLength(
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ write((byte)length);
+ }
+ }
+
+ void writeEncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ write(tag);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ void writeTag(int flags, int tagNo)
+ throws IOException
+ {
+ if (tagNo < 31)
+ {
+ write(flags | tagNo);
+ }
+ else
+ {
+ write(flags | 0x1f);
+ if (tagNo < 128)
+ {
+ write(tagNo);
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ write(stack, pos, stack.length - pos);
+ }
+ }
+ }
+
+ void writeEncoded(int flags, int tagNo, byte[] bytes)
+ throws IOException
+ {
+ writeTag(flags, tagNo);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ protected void writeNull()
+ throws IOException
+ {
+ write(NULL);
+ write(0x00);
+ }
+
+ public void write(byte[] buf)
+ throws IOException
+ {
+ out.write(buf, 0, buf.length);
+ }
+
+ public void write(byte[] buf, int offSet, int len)
+ throws IOException
+ {
+ out.write(buf, offSet, len);
+ }
+
+ public void writeObject(
+ Object obj)
+ throws IOException
+ {
+ if (obj == null)
+ {
+ writeNull();
+ }
+ else if (obj instanceof DERObject)
+ {
+ ((DERObject)obj).encode(this);
+ }
+ else if (obj instanceof DEREncodable)
+ {
+ ((DEREncodable)obj).getDERObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("object not DEREncodable");
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERPrintableString.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERPrintableString.java
new file mode 100644
index 00000000..032823dd
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERPrintableString.java
@@ -0,0 +1,204 @@
+package org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER PrintableString object.
+ */
+public class DERPrintableString
+ extends ASN1Object
+ implements DERString
+{
+ String string;
+
+ /**
+ * return a printable string from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERPrintableString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERPrintableString)
+ {
+ return (DERPrintableString)obj;
+ }
+
+ if (obj instanceof ASN1OctetString)
+ {
+ return new DERPrintableString(((ASN1OctetString)obj).getOctets());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Printable 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.
+ */
+ public static DERPrintableString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERPrintableString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(string[i] & 0xff);
+ }
+
+ this.string = new String(cs);
+ }
+
+ /**
+ * basic constructor - this does not validate the string
+ */
+ public DERPrintableString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a PrintableString.
+ */
+ public DERPrintableString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isPrintableString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ return string;
+ }
+
+ public byte[] getOctets()
+ {
+ char[] cs = string.toCharArray();
+ byte[] bs = new byte[cs.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ bs[i] = (byte)cs[i];
+ }
+
+ return bs;
+ }
+
+ void encode(
+ DEROutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(PRINTABLE_STRING, this.getOctets());
+ }
+
+ public int hashCode()
+ {
+ return this.getString().hashCode();
+ }
+
+ boolean asn1Equals(
+ DERObject o)
+ {
+ if (!(o instanceof DERPrintableString))
+ {
+ return false;
+ }
+
+ DERPrintableString s = (DERPrintableString)o;
+
+ return this.getString().equals(s.getString());
+ }
+
+ public String toString()
+ {
+ return string;
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static boolean isPrintableString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if ('a' <= ch && ch <= 'z')
+ {
+ continue;
+ }
+
+ if ('A' <= ch && ch <= 'Z')
+ {
+ continue;
+ }
+
+ if ('0' <= ch && ch <= '9')
+ {
+ continue;
+ }
+
+ switch (ch)
+ {
+ case ' ':
+ case '\'':
+ case '(':
+ case ')':
+ case '+':
+ case '-':
+ case '.':
+ case ':':
+ case '=':
+ case '?':
+ case '/':
+ case ',':
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequence.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequence.java
new file mode 100644
index 00000000..593dfe99
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/DERSequence.java
@@ -0,0 +1,81 @@
+package org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+
+@SuppressWarnings("unchecked")
+public class DERSequence
+ extends ASN1Sequence
+{
+ /**
+ * create an empty sequence
+ */
+ public DERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public DERSequence(
+ DEREncodable obj)
+ {
+ this.addObject(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public DERSequence(
+ DEREncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ this.addObject(v.get(i));
+ }
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public DERSequence(
+ ASN1Encodable[] a)
+ {
+ for (int i = 0; i != a.length; i++)
+ {
+ this.addObject(a[i]);
+ }
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ *
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ */
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
new file mode 100644
index 00000000..fe04a5c6
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
@@ -0,0 +1,47 @@
+package org.bouncycastle.asn1.pkcs;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.DERObject;
+
+public class AuthenticatedSafe
+ extends ASN1Encodable
+{
+ ContentInfo[] info;
+
+ public AuthenticatedSafe(
+ ASN1Sequence seq)
+ {
+ info = new ContentInfo[seq.size()];
+
+ for (int i = 0; i != info.length; i++)
+ {
+ info[i] = ContentInfo.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public AuthenticatedSafe(
+ ContentInfo[] info)
+ {
+ this.info = info;
+ }
+
+ public ContentInfo[] getContentInfo()
+ {
+ return info;
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != info.length; i++)
+ {
+ v.add(info[i]);
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/CertBag.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/CertBag.java
new file mode 100644
index 00000000..c781b4c3
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/CertBag.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.asn1.pkcs;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+public class CertBag
+ extends ASN1Encodable
+{
+ ASN1Sequence seq;
+ DERObjectIdentifier certId;
+ DERObject certValue;
+
+ public CertBag(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ this.certId = (DERObjectIdentifier)seq.getObjectAt(0);
+ this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ }
+
+ public CertBag(
+ DERObjectIdentifier certId,
+ DERObject certValue)
+ {
+ this.certId = certId;
+ this.certValue = certValue;
+ }
+
+ public DERObjectIdentifier getCertId()
+ {
+ return certId;
+ }
+
+ public DERObject getCertValue()
+ {
+ return certValue;
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certId);
+ v.add(new DERTaggedObject(0, certValue));
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/ContentInfo.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/ContentInfo.java
new file mode 100644
index 00000000..06b03ffd
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/ContentInfo.java
@@ -0,0 +1,91 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.BERTaggedObject;
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERTaggedObject;
+
+@SuppressWarnings("unchecked")
+public class ContentInfo
+ extends ASN1Encodable
+ implements PKCSObjectIdentifiers
+{
+ private DERObjectIdentifier contentType;
+ private DEREncodable content;
+
+ public static ContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ContentInfo)
+ {
+ return (ContentInfo)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new ContentInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public ContentInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ contentType = (DERObjectIdentifier)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ content = ((DERTaggedObject)e.nextElement()).getObject();
+ }
+ }
+
+ public ContentInfo(
+ DERObjectIdentifier contentType,
+ DEREncodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public DERObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public DEREncodable getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ *
+ */
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+
+ if (content != null)
+ {
+ v.add(new BERTaggedObject(0, content));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/DHParameter.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/DHParameter.java
new file mode 100644
index 00000000..4ab8cf70
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/DHParameter.java
@@ -0,0 +1,89 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERSequence;
+
+@SuppressWarnings("unchecked")
+public class DHParameter
+ extends ASN1Encodable
+{
+ DERInteger p, g, l;
+
+ public DHParameter(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.p = new DERInteger(p);
+ this.g = new DERInteger(g);
+
+ if (l != 0)
+ {
+ this.l = new DERInteger(l);
+ }
+ else
+ {
+ this.l = null;
+ }
+ }
+
+ public DHParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = (DERInteger)e.nextElement();
+ g = (DERInteger)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ l = (DERInteger)e.nextElement();
+ }
+ else
+ {
+ l = null;
+ }
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public BigInteger getL()
+ {
+ if (l == null)
+ {
+ return null;
+ }
+
+ return l.getPositiveValue();
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ if (this.getL() != null)
+ {
+ v.add(l);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
new file mode 100644
index 00000000..9fe14bd8
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
@@ -0,0 +1,99 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+
+@SuppressWarnings("unchecked")
+public class PBKDF2Params
+ extends ASN1Encodable
+{
+ ASN1OctetString octStr;
+ DERInteger iterationCount;
+ DERInteger keyLength;
+
+ public static PBKDF2Params getInstance(
+ Object obj)
+ {
+ if (obj instanceof PBKDF2Params)
+ {
+ return (PBKDF2Params)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new PBKDF2Params((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount)
+ {
+ this.octStr = new DEROctetString(salt);
+ this.iterationCount = new DERInteger(iterationCount);
+ }
+
+ public PBKDF2Params(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ octStr = (ASN1OctetString)e.nextElement();
+ iterationCount = (DERInteger)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ keyLength = (DERInteger)e.nextElement();
+ }
+ else
+ {
+ keyLength = null;
+ }
+ }
+
+ public byte[] getSalt()
+ {
+ return octStr.getOctets();
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterationCount.getValue();
+ }
+
+ public BigInteger getKeyLength()
+ {
+ if (keyLength != null)
+ {
+ return keyLength.getValue();
+ }
+
+ return null;
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(octStr);
+ v.add(iterationCount);
+
+ if (keyLength != null)
+ {
+ v.add(keyLength);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
new file mode 100644
index 00000000..8817b35c
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
@@ -0,0 +1,69 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+
+public class PKCS12PBEParams
+ extends ASN1Encodable
+{
+ DERInteger iterations;
+ ASN1OctetString iv;
+
+ public PKCS12PBEParams(
+ byte[] salt,
+ int iterations)
+ {
+ this.iv = new DEROctetString(salt);
+ this.iterations = new DERInteger(iterations);
+ }
+
+ public PKCS12PBEParams(
+ ASN1Sequence seq)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ iterations = (DERInteger)seq.getObjectAt(1);
+ }
+
+ public static PKCS12PBEParams getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKCS12PBEParams)
+ {
+ return (PKCS12PBEParams)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new PKCS12PBEParams((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public BigInteger getIterations()
+ {
+ return iterations.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(iterations);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
new file mode 100644
index 00000000..19af2d67
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
@@ -0,0 +1,248 @@
+package org.bouncycastle.asn1.pkcs;
+
+import org.bouncycastle.asn1.DERObjectIdentifier;
+
+public interface PKCSObjectIdentifiers
+{
+ //
+ // pkcs-1 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ //
+ static final String pkcs_1 = "1.2.840.113549.1.1";
+ static final DERObjectIdentifier rsaEncryption = new DERObjectIdentifier(pkcs_1 + ".1");
+ static final DERObjectIdentifier md2WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".2");
+ static final DERObjectIdentifier md4WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".3");
+ static final DERObjectIdentifier md5WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".4");
+ static final DERObjectIdentifier sha1WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".5");
+ static final DERObjectIdentifier srsaOAEPEncryptionSET = new DERObjectIdentifier(pkcs_1 + ".6");
+ static final DERObjectIdentifier id_RSAES_OAEP = new DERObjectIdentifier(pkcs_1 + ".7");
+ static final DERObjectIdentifier id_mgf1 = new DERObjectIdentifier(pkcs_1 + ".8");
+ static final DERObjectIdentifier id_pSpecified = new DERObjectIdentifier(pkcs_1 + ".9");
+ static final DERObjectIdentifier id_RSASSA_PSS = new DERObjectIdentifier(pkcs_1 + ".10");
+ static final DERObjectIdentifier sha256WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".11");
+ static final DERObjectIdentifier sha384WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".12");
+ static final DERObjectIdentifier sha512WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".13");
+ static final DERObjectIdentifier sha224WithRSAEncryption = new DERObjectIdentifier(pkcs_1 + ".14");
+
+ //
+ // pkcs-3 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
+ //
+ static final String pkcs_3 = "1.2.840.113549.1.3";
+ static final DERObjectIdentifier dhKeyAgreement = new DERObjectIdentifier(pkcs_3 + ".1");
+
+ //
+ // pkcs-5 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
+ //
+ static final String pkcs_5 = "1.2.840.113549.1.5";
+
+ static final DERObjectIdentifier pbeWithMD2AndDES_CBC = new DERObjectIdentifier(pkcs_5 + ".1");
+ static final DERObjectIdentifier pbeWithMD2AndRC2_CBC = new DERObjectIdentifier(pkcs_5 + ".4");
+ static final DERObjectIdentifier pbeWithMD5AndDES_CBC = new DERObjectIdentifier(pkcs_5 + ".3");
+ static final DERObjectIdentifier pbeWithMD5AndRC2_CBC = new DERObjectIdentifier(pkcs_5 + ".6");
+ static final DERObjectIdentifier pbeWithSHA1AndDES_CBC = new DERObjectIdentifier(pkcs_5 + ".10");
+ static final DERObjectIdentifier pbeWithSHA1AndRC2_CBC = new DERObjectIdentifier(pkcs_5 + ".11");
+
+ static final DERObjectIdentifier id_PBES2 = new DERObjectIdentifier(pkcs_5 + ".13");
+
+ static final DERObjectIdentifier id_PBKDF2 = new DERObjectIdentifier(pkcs_5 + ".12");
+
+ //
+ // encryptionAlgorithm OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) 3 }
+ //
+ static final String encryptionAlgorithm = "1.2.840.113549.3";
+
+ static final DERObjectIdentifier des_EDE3_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".7");
+ static final DERObjectIdentifier RC2_CBC = new DERObjectIdentifier(encryptionAlgorithm + ".2");
+
+ //
+ // object identifiers for digests
+ //
+ static final String digestAlgorithm = "1.2.840.113549.2";
+ //
+ // md2 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
+ //
+ static final DERObjectIdentifier md2 = new DERObjectIdentifier(digestAlgorithm + ".2");
+
+ //
+ // md4 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 4}
+ //
+ static final DERObjectIdentifier md4 = new DERObjectIdentifier(digestAlgorithm + ".4");
+
+ //
+ // md5 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
+ //
+ static final DERObjectIdentifier md5 = new DERObjectIdentifier(digestAlgorithm + ".5");
+
+ static final DERObjectIdentifier id_hmacWithSHA1 = new DERObjectIdentifier(digestAlgorithm + ".7");
+ static final DERObjectIdentifier id_hmacWithSHA224 = new DERObjectIdentifier(digestAlgorithm + ".8");
+ static final DERObjectIdentifier id_hmacWithSHA256 = new DERObjectIdentifier(digestAlgorithm + ".9");
+ static final DERObjectIdentifier id_hmacWithSHA384 = new DERObjectIdentifier(digestAlgorithm + ".10");
+ static final DERObjectIdentifier id_hmacWithSHA512 = new DERObjectIdentifier(digestAlgorithm + ".11");
+
+ //
+ // pkcs-7 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
+ //
+ static final String pkcs_7 = "1.2.840.113549.1.7";
+ static final DERObjectIdentifier data = new DERObjectIdentifier(pkcs_7 + ".1");
+ static final DERObjectIdentifier signedData = new DERObjectIdentifier(pkcs_7 + ".2");
+ static final DERObjectIdentifier envelopedData = new DERObjectIdentifier(pkcs_7 + ".3");
+ static final DERObjectIdentifier signedAndEnvelopedData = new DERObjectIdentifier(pkcs_7 + ".4");
+ static final DERObjectIdentifier digestedData = new DERObjectIdentifier(pkcs_7 + ".5");
+ static final DERObjectIdentifier encryptedData = new DERObjectIdentifier(pkcs_7 + ".6");
+
+ //
+ // pkcs-9 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+ //
+ static final String pkcs_9 = "1.2.840.113549.1.9";
+
+ static final DERObjectIdentifier pkcs_9_at_emailAddress = new DERObjectIdentifier(pkcs_9 + ".1");
+ static final DERObjectIdentifier pkcs_9_at_unstructuredName = new DERObjectIdentifier(pkcs_9 + ".2");
+ static final DERObjectIdentifier pkcs_9_at_contentType = new DERObjectIdentifier(pkcs_9 + ".3");
+ static final DERObjectIdentifier pkcs_9_at_messageDigest = new DERObjectIdentifier(pkcs_9 + ".4");
+ static final DERObjectIdentifier pkcs_9_at_signingTime = new DERObjectIdentifier(pkcs_9 + ".5");
+ static final DERObjectIdentifier pkcs_9_at_counterSignature = new DERObjectIdentifier(pkcs_9 + ".6");
+ static final DERObjectIdentifier pkcs_9_at_challengePassword = new DERObjectIdentifier(pkcs_9 + ".7");
+ static final DERObjectIdentifier pkcs_9_at_unstructuredAddress = new DERObjectIdentifier(pkcs_9 + ".8");
+ static final DERObjectIdentifier pkcs_9_at_extendedCertificateAttributes = new DERObjectIdentifier(pkcs_9 + ".9");
+
+ static final DERObjectIdentifier pkcs_9_at_signingDescription = new DERObjectIdentifier(pkcs_9 + ".13");
+ static final DERObjectIdentifier pkcs_9_at_extensionRequest = new DERObjectIdentifier(pkcs_9 + ".14");
+ static final DERObjectIdentifier pkcs_9_at_smimeCapabilities = new DERObjectIdentifier(pkcs_9 + ".15");
+
+ static final DERObjectIdentifier pkcs_9_at_friendlyName = new DERObjectIdentifier(pkcs_9 + ".20");
+ static final DERObjectIdentifier pkcs_9_at_localKeyId = new DERObjectIdentifier(pkcs_9 + ".21");
+
+ /** @deprecated use x509Certificate instead */
+ static final DERObjectIdentifier x509certType = new DERObjectIdentifier(pkcs_9 + ".22.1");
+
+ static final String certTypes = pkcs_9 + ".22";
+ static final DERObjectIdentifier x509Certificate = new DERObjectIdentifier(certTypes + ".1");
+ static final DERObjectIdentifier sdsiCertificate = new DERObjectIdentifier(certTypes + ".2");
+
+ static final String crlTypes = pkcs_9 + ".23";
+ static final DERObjectIdentifier x509Crl = new DERObjectIdentifier(crlTypes + ".1");
+
+ static final DERObjectIdentifier id_alg_PWRI_KEK = new DERObjectIdentifier(pkcs_9 + ".16.3.9");
+
+ //
+ // SMIME capability sub oids.
+ //
+ static final DERObjectIdentifier preferSignedData = new DERObjectIdentifier(pkcs_9 + ".15.1");
+ static final DERObjectIdentifier canNotDecryptAny = new DERObjectIdentifier(pkcs_9 + ".15.2");
+ static final DERObjectIdentifier sMIMECapabilitiesVersions = new DERObjectIdentifier(pkcs_9 + ".15.3");
+
+ //
+ // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
+ //
+ static String id_ct = "1.2.840.113549.1.9.16.1";
+
+ static final DERObjectIdentifier id_ct_authData = new DERObjectIdentifier(id_ct + ".2");
+ static final DERObjectIdentifier id_ct_TSTInfo = new DERObjectIdentifier(id_ct + ".4");
+ static final DERObjectIdentifier id_ct_compressedData = new DERObjectIdentifier(id_ct + ".9");
+ static final DERObjectIdentifier id_ct_authEnvelopedData = new DERObjectIdentifier(id_ct + ".23");
+
+ //
+ // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
+ //
+ static String id_cti = "1.2.840.113549.1.9.16.6";
+
+ static final DERObjectIdentifier id_cti_ets_proofOfOrigin = new DERObjectIdentifier(id_cti + ".1");
+ static final DERObjectIdentifier id_cti_ets_proofOfReceipt = new DERObjectIdentifier(id_cti + ".2");
+ static final DERObjectIdentifier id_cti_ets_proofOfDelivery = new DERObjectIdentifier(id_cti + ".3");
+ static final DERObjectIdentifier id_cti_ets_proofOfSender = new DERObjectIdentifier(id_cti + ".4");
+ static final DERObjectIdentifier id_cti_ets_proofOfApproval = new DERObjectIdentifier(id_cti + ".5");
+ static final DERObjectIdentifier id_cti_ets_proofOfCreation = new DERObjectIdentifier(id_cti + ".6");
+
+ //
+ // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
+ //
+ static String id_aa = "1.2.840.113549.1.9.16.2";
+
+ static final DERObjectIdentifier id_aa_receiptRequest = new DERObjectIdentifier(id_aa + ".1");
+
+ static final DERObjectIdentifier id_aa_contentHint = new DERObjectIdentifier(id_aa + ".4"); // See RFC 2634
+ /*
+ * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
+ *
+ */
+ static final DERObjectIdentifier id_aa_encrypKeyPref = new DERObjectIdentifier(id_aa + ".11");
+ static final DERObjectIdentifier id_aa_signingCertificate = new DERObjectIdentifier(id_aa + ".12");
+ static final DERObjectIdentifier id_aa_signingCertificateV2 = new DERObjectIdentifier(id_aa + ".47");
+
+ static final DERObjectIdentifier id_aa_contentIdentifier = new DERObjectIdentifier(id_aa + ".7"); // See RFC 2634
+
+ /*
+ * RFC 3126
+ */
+ static final DERObjectIdentifier id_aa_signatureTimeStampToken = new DERObjectIdentifier(id_aa + ".14");
+
+ static final DERObjectIdentifier id_aa_ets_sigPolicyId = new DERObjectIdentifier(id_aa + ".15");
+ static final DERObjectIdentifier id_aa_ets_commitmentType = new DERObjectIdentifier(id_aa + ".16");
+ static final DERObjectIdentifier id_aa_ets_signerLocation = new DERObjectIdentifier(id_aa + ".17");
+ static final DERObjectIdentifier id_aa_ets_signerAttr = new DERObjectIdentifier(id_aa + ".18");
+ static final DERObjectIdentifier id_aa_ets_otherSigCert = new DERObjectIdentifier(id_aa + ".19");
+ static final DERObjectIdentifier id_aa_ets_contentTimestamp = new DERObjectIdentifier(id_aa + ".20");
+ static final DERObjectIdentifier id_aa_ets_certificateRefs = new DERObjectIdentifier(id_aa + ".21");
+ static final DERObjectIdentifier id_aa_ets_revocationRefs = new DERObjectIdentifier(id_aa + ".22");
+ static final DERObjectIdentifier id_aa_ets_certValues = new DERObjectIdentifier(id_aa + ".23");
+ static final DERObjectIdentifier id_aa_ets_revocationValues = new DERObjectIdentifier(id_aa + ".24");
+ static final DERObjectIdentifier id_aa_ets_escTimeStamp = new DERObjectIdentifier(id_aa + ".25");
+ static final DERObjectIdentifier id_aa_ets_certCRLTimestamp = new DERObjectIdentifier(id_aa + ".26");
+ static final DERObjectIdentifier id_aa_ets_archiveTimestamp = new DERObjectIdentifier(id_aa + ".27");
+
+ /** @deprecated use id_aa_ets_sigPolicyId instead */
+ static final DERObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
+ /** @deprecated use id_aa_ets_commitmentType instead */
+ static final DERObjectIdentifier id_aa_commitmentType = id_aa_ets_commitmentType;
+ /** @deprecated use id_aa_ets_signerLocation instead */
+ static final DERObjectIdentifier id_aa_signerLocation = id_aa_ets_signerLocation;
+ /** @deprecated use id_aa_ets_otherSigCert instead */
+ static final DERObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
+
+ //
+ // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
+ //
+ final String id_spq = "1.2.840.113549.1.9.16.5";
+
+ static final DERObjectIdentifier id_spq_ets_uri = new DERObjectIdentifier(id_spq + ".1");
+ static final DERObjectIdentifier id_spq_ets_unotice = new DERObjectIdentifier(id_spq + ".2");
+
+ //
+ // pkcs-12 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
+ //
+ static final String pkcs_12 = "1.2.840.113549.1.12";
+ static final String bagtypes = pkcs_12 + ".10.1";
+
+ static final DERObjectIdentifier keyBag = new DERObjectIdentifier(bagtypes + ".1");
+ static final DERObjectIdentifier pkcs8ShroudedKeyBag = new DERObjectIdentifier(bagtypes + ".2");
+ static final DERObjectIdentifier certBag = new DERObjectIdentifier(bagtypes + ".3");
+ static final DERObjectIdentifier crlBag = new DERObjectIdentifier(bagtypes + ".4");
+ static final DERObjectIdentifier secretBag = new DERObjectIdentifier(bagtypes + ".5");
+ static final DERObjectIdentifier safeContentsBag = new DERObjectIdentifier(bagtypes + ".6");
+
+ static final String pkcs_12PbeIds = pkcs_12 + ".1";
+
+ static final DERObjectIdentifier pbeWithSHAAnd128BitRC4 = new DERObjectIdentifier(pkcs_12PbeIds + ".1");
+ static final DERObjectIdentifier pbeWithSHAAnd40BitRC4 = new DERObjectIdentifier(pkcs_12PbeIds + ".2");
+ static final DERObjectIdentifier pbeWithSHAAnd3_KeyTripleDES_CBC = new DERObjectIdentifier(pkcs_12PbeIds + ".3");
+ static final DERObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = new DERObjectIdentifier(pkcs_12PbeIds + ".4");
+ static final DERObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = new DERObjectIdentifier(pkcs_12PbeIds + ".5");
+ static final DERObjectIdentifier pbewithSHAAnd40BitRC2_CBC = new DERObjectIdentifier(pkcs_12PbeIds + ".6");
+
+ static final DERObjectIdentifier id_alg_CMS3DESwrap = new DERObjectIdentifier("1.2.840.113549.1.9.16.3.6");
+ static final DERObjectIdentifier id_alg_CMSRC2wrap = new DERObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+}
+
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
new file mode 100644
index 00000000..23508a42
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
@@ -0,0 +1,89 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+
+public class RC2CBCParameter
+ extends ASN1Encodable
+{
+ DERInteger version;
+ ASN1OctetString iv;
+
+ public static RC2CBCParameter getInstance(
+ Object o)
+ {
+ if (o instanceof ASN1Sequence)
+ {
+ return new RC2CBCParameter((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in RC2CBCParameter factory");
+ }
+
+ public RC2CBCParameter(
+ byte[] iv)
+ {
+ this.version = null;
+ this.iv = new DEROctetString(iv);
+ }
+
+ public RC2CBCParameter(
+ int parameterVersion,
+ byte[] iv)
+ {
+ this.version = new DERInteger(parameterVersion);
+ this.iv = new DEROctetString(iv);
+ }
+
+ public RC2CBCParameter(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 1)
+ {
+ version = null;
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ }
+ else
+ {
+ version = (DERInteger)seq.getObjectAt(0);
+ iv = (ASN1OctetString)seq.getObjectAt(1);
+ }
+ }
+
+ public BigInteger getRC2ParameterVersion()
+ {
+ if (version == null)
+ {
+ return null;
+ }
+
+ return version.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != null)
+ {
+ v.add(version);
+ }
+
+ v.add(iv);
+
+ return new DERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
new file mode 100644
index 00000000..b931ee7d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
@@ -0,0 +1,187 @@
+package org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERSequence;
+
+@SuppressWarnings("unchecked")
+public class RSAPrivateKeyStructure
+ extends ASN1Encodable
+{
+ private int version;
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger prime1;
+ private BigInteger prime2;
+ private BigInteger exponent1;
+ private BigInteger exponent2;
+ private BigInteger coefficient;
+ private ASN1Sequence otherPrimeInfos = null;
+
+ public static RSAPrivateKeyStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPrivateKeyStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPrivateKeyStructure)
+ {
+ return (RSAPrivateKeyStructure)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new RSAPrivateKeyStructure((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public RSAPrivateKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.version = 0;
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ public RSAPrivateKeyStructure(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger v = ((DERInteger)e.nextElement()).getValue();
+ if (v.intValue() != 0 && v.intValue() != 1)
+ {
+ throw new IllegalArgumentException("wrong version for RSA private key");
+ }
+
+ version = v.intValue();
+ modulus = ((DERInteger)e.nextElement()).getValue();
+ publicExponent = ((DERInteger)e.nextElement()).getValue();
+ privateExponent = ((DERInteger)e.nextElement()).getValue();
+ prime1 = ((DERInteger)e.nextElement()).getValue();
+ prime2 = ((DERInteger)e.nextElement()).getValue();
+ exponent1 = ((DERInteger)e.nextElement()).getValue();
+ exponent2 = ((DERInteger)e.nextElement()).getValue();
+ coefficient = ((DERInteger)e.nextElement()).getValue();
+
+ if (e.hasMoreElements())
+ {
+ otherPrimeInfos = (ASN1Sequence)e.nextElement();
+ }
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+
+ public BigInteger getPrime1()
+ {
+ return prime1;
+ }
+
+ public BigInteger getPrime2()
+ {
+ return prime2;
+ }
+
+ public BigInteger getExponent1()
+ {
+ return exponent1;
+ }
+
+ public BigInteger getExponent2()
+ {
+ return exponent2;
+ }
+
+ public BigInteger getCoefficient()
+ {
+ return coefficient;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * Version ::= INTEGER { two-prime(0), multi(1) }
+ * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
+ *
+ *
+ * SignedData ::= SEQUENCE {
+ * version Version,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates
+ * [0] IMPLICIT ExtendedCertificatesAndCertificates
+ * OPTIONAL,
+ * crls
+ * [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ *
+ */
+ public DERObject toASN1Object()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithms);
+ v.add(contentInfo);
+
+ if (certificates != null)
+ {
+ v.add(new DERTaggedObject(false, 0, certificates));
+ }
+
+ if (crls != null)
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+
+ v.add(signerInfos);
+
+ return new BERSequence(v);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java
new file mode 100644
index 00000000..250fac1d
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java
@@ -0,0 +1,473 @@
+package org.bouncycastle.asn1.util;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BERApplicationSpecific;
+import org.bouncycastle.asn1.BERConstructedOctetString;
+import org.bouncycastle.asn1.BERConstructedSequence;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.BERSet;
+import org.bouncycastle.asn1.BERTaggedObject;
+import org.bouncycastle.asn1.DERApplicationSpecific;
+import org.bouncycastle.asn1.DERBMPString;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.DERBoolean;
+import org.bouncycastle.asn1.DERConstructedSequence;
+import org.bouncycastle.asn1.DERConstructedSet;
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.DEREnumerated;
+import org.bouncycastle.asn1.DERExternal;
+import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.asn1.DERIA5String;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERPrintableString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERT61String;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.DERTags;
+import org.bouncycastle.asn1.DERUTCTime;
+import org.bouncycastle.asn1.DERUTF8String;
+import org.bouncycastle.asn1.DERUnknownTag;
+import org.bouncycastle.asn1.DERVisibleString;
+import org.bouncycastle.util.encoders.Hex;
+
+@SuppressWarnings({ "unchecked", "deprecation" })
+public class ASN1Dump
+{
+ private static final String TAB = " ";
+ private static final int SAMPLE_SIZE = 32;
+
+ /**
+ * dump a DER object as a formatted string with indentation
+ *
+ * @param obj the DERObject to be dumped out.
+ */
+ static void _dumpAsString(
+ String indent,
+ boolean verbose,
+ DERObject obj,
+ StringBuffer buf)
+ {
+ String nl = System.getProperty("line.separator");
+ if (obj instanceof ASN1Sequence)
+ {
+ Enumeration e = ((ASN1Sequence)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERConstructedSequence)
+ {
+ buf.append("BER ConstructedSequence");
+ }
+ else if (obj instanceof DERConstructedSequence)
+ {
+ buf.append("DER ConstructedSequence");
+ }
+ else if (obj instanceof BERSequence)
+ {
+ buf.append("BER Sequence");
+ }
+ else if (obj instanceof DERSequence)
+ {
+ buf.append("DER Sequence");
+ }
+ else
+ {
+ buf.append("Sequence");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null || o.equals(new DERNull()))
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ _dumpAsString(tab, verbose, (DERObject)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject(), buf);
+ }
+ }
+ }
+ else if (obj instanceof DERTaggedObject)
+ {
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERTaggedObject)
+ {
+ buf.append("BER Tagged [");
+ }
+ else
+ {
+ buf.append("Tagged [");
+ }
+
+ DERTaggedObject o = (DERTaggedObject)obj;
+
+ buf.append(Integer.toString(o.getTagNo()));
+ buf.append(']');
+
+ if (!o.isExplicit())
+ {
+ buf.append(" IMPLICIT ");
+ }
+
+ buf.append(nl);
+
+ if (o.isEmpty())
+ {
+ buf.append(tab);
+ buf.append("EMPTY");
+ buf.append(nl);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, o.getObject(), buf);
+ }
+ }
+ else if (obj instanceof DERConstructedSet)
+ {
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("ConstructedSet");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ _dumpAsString(tab, verbose, (DERObject)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject(), buf);
+ }
+ }
+ }
+ else if (obj instanceof BERSet)
+ {
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("BER Set");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ _dumpAsString(tab, verbose, (DERObject)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject(), buf);
+ }
+ }
+ }
+ else if (obj instanceof DERSet)
+ {
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("DER Set");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ _dumpAsString(tab, verbose, (DERObject)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject(), buf);
+ }
+ }
+ }
+ else if (obj instanceof DERObjectIdentifier)
+ {
+ buf.append(indent + "ObjectIdentifier(" + ((DERObjectIdentifier)obj).getId() + ")" + nl);
+ }
+ else if (obj instanceof DERBoolean)
+ {
+ buf.append(indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl);
+ }
+ else if (obj instanceof DERInteger)
+ {
+ buf.append(indent + "Integer(" + ((DERInteger)obj).getValue() + ")" + nl);
+ }
+ else if (obj instanceof BERConstructedOctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+ buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
+ }
+ else{
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+ buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] ");
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
+ }
+ else{
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof DERBitString)
+ {
+ DERBitString bt = (DERBitString)obj;
+ buf.append(indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] ");
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, bt.getBytes()));
+ }
+ else{
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ buf.append(indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ buf.append(indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERPrintableString)
+ {
+ buf.append(indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERVisibleString)
+ {
+ buf.append(indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERBMPString)
+ {
+ buf.append(indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERT61String)
+ {
+ buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERUTCTime)
+ {
+ buf.append(indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof DERGeneralizedTime)
+ {
+ buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof DERUnknownTag)
+ {
+ buf.append(indent + "Unknown " + Integer.toString(((DERUnknownTag)obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag)obj).getData())) + nl);
+ }
+ else if (obj instanceof BERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof DERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof DEREnumerated)
+ {
+ DEREnumerated en = (DEREnumerated) obj;
+ buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
+ }
+ else if (obj instanceof DERExternal)
+ {
+ DERExternal ext = (DERExternal) obj;
+ buf.append(indent + "External " + nl);
+ String tab = indent + TAB;
+ if (ext.getDirectReference() != null)
+ {
+ buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl);
+ }
+ if (ext.getIndirectReference() != null)
+ {
+ buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl);
+ }
+ if (ext.getDataValueDescriptor() != null)
+ {
+ _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf);
+ }
+ buf.append(tab + "Encoding: " + ext.getEncoding() + nl);
+ _dumpAsString(tab, verbose, ext.getExternalContent(), buf);
+ }
+ else
+ {
+ buf.append(indent + obj.toString() + nl);
+ }
+ }
+
+ private static String outputApplicationSpecific(String type, String indent, boolean verbose, DERObject obj, String nl)
+ {
+ DERApplicationSpecific app = (DERApplicationSpecific)obj;
+ StringBuffer buf = new StringBuffer();
+
+ if (app.isConstructed())
+ {
+ try
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(DERTags.SEQUENCE));
+ buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
+ for (Enumeration e = s.getObjects(); e.hasMoreElements();)
+ {
+ _dumpAsString(indent + TAB, verbose, (DERObject)e.nextElement(), buf);
+ }
+ }
+ catch (IOException e)
+ {
+ buf.append(e);
+ }
+ return buf.toString();
+ }
+
+ return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
+ }
+
+ /**
+ * dump out a DER object as a formatted string, in non-verbose mode.
+ *
+ * @param obj the DERObject to be dumped out.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj)
+ {
+ return dumpAsString(obj, false);
+ }
+
+ /**
+ * Dump out the object as a string.
+ *
+ * @param obj the object to be dumped
+ * @param verbose if true, dump out the contents of octet and bit strings.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj,
+ boolean verbose)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ if (obj instanceof DERObject)
+ {
+ _dumpAsString("", verbose, (DERObject)obj, buf);
+ }
+ else if (obj instanceof DEREncodable)
+ {
+ _dumpAsString("", verbose, ((DEREncodable)obj).getDERObject(), buf);
+ }
+ else
+ {
+ return "unknown object type " + obj.toString();
+ }
+
+ return buf.toString();
+ }
+
+ private static String dumpBinaryDataAsString(String indent, byte[] bytes)
+ {
+ String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ indent += TAB;
+
+ buf.append(nl);
+ for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
+ {
+ if (bytes.length - i > SAMPLE_SIZE)
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
+ buf.append(nl);
+ }
+ else
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
+ for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
+ {
+ buf.append(" ");
+ }
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, bytes.length - i));
+ buf.append(nl);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static String calculateAscString(byte[] bytes, int off, int len)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ for (int i = off; i != off + len; i++)
+ {
+ if (bytes[i] >= ' ' && bytes[i] <= '~')
+ {
+ buf.append((char)bytes[i]);
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java.orig b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java.orig
new file mode 100644
index 00000000..68c65cbe
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/ASN1Dump.java.orig
@@ -0,0 +1,440 @@
+package org.bouncycastle.asn1.util;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BERConstructedOctetString;
+import org.bouncycastle.asn1.BERConstructedSequence;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.BERSet;
+import org.bouncycastle.asn1.BERTaggedObject;
+import org.bouncycastle.asn1.DERBMPString;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.DERBoolean;
+import org.bouncycastle.asn1.DERConstructedSequence;
+import org.bouncycastle.asn1.DERConstructedSet;
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.DERGeneralizedTime;
+import org.bouncycastle.asn1.DERIA5String;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERPrintableString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERT61String;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.DERUTCTime;
+import org.bouncycastle.asn1.DERUTF8String;
+import org.bouncycastle.asn1.DERUnknownTag;
+import org.bouncycastle.asn1.DERVisibleString;
+import org.bouncycastle.asn1.DERApplicationSpecific;
+import org.bouncycastle.asn1.DERTags;
+import org.bouncycastle.asn1.BERApplicationSpecific;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.util.Enumeration;
+import java.io.IOException;
+
+public class ASN1Dump
+{
+ private static final String TAB = " ";
+ private static final int SAMPLE_SIZE = 32;
+
+ /**
+ * dump a DER object as a formatted string with indentation
+ *
+ * @param obj the DERObject to be dumped out.
+ */
+ static String _dumpAsString(
+ String indent,
+ boolean verbose,
+ DERObject obj)
+ {
+ String nl = System.getProperty("line.separator");
+ if (obj instanceof ASN1Sequence)
+ {
+ StringBuffer buf = new StringBuffer();
+ Enumeration e = ((ASN1Sequence)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERConstructedSequence)
+ {
+ buf.append("BER ConstructedSequence");
+ }
+ else if (obj instanceof DERConstructedSequence)
+ {
+ buf.append("DER ConstructedSequence");
+ }
+ else if (obj instanceof BERSequence)
+ {
+ buf.append("BER Sequence");
+ }
+ else if (obj instanceof DERSequence)
+ {
+ buf.append("DER Sequence");
+ }
+ else
+ {
+ buf.append("Sequence");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null || o.equals(new DERNull()))
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ buf.append(_dumpAsString(tab, verbose, (DERObject)o));
+ }
+ else
+ {
+ buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject()));
+ }
+ }
+ return buf.toString();
+ }
+ else if (obj instanceof DERTaggedObject)
+ {
+ StringBuffer buf = new StringBuffer();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERTaggedObject)
+ {
+ buf.append("BER Tagged [");
+ }
+ else
+ {
+ buf.append("Tagged [");
+ }
+
+ DERTaggedObject o = (DERTaggedObject)obj;
+
+ buf.append(Integer.toString(o.getTagNo()));
+ buf.append(']');
+
+ if (!o.isExplicit())
+ {
+ buf.append(" IMPLICIT ");
+ }
+
+ buf.append(nl);
+
+ if (o.isEmpty())
+ {
+ buf.append(tab);
+ buf.append("EMPTY");
+ buf.append(nl);
+ }
+ else
+ {
+ buf.append(_dumpAsString(tab, verbose, o.getObject()));
+ }
+
+ return buf.toString();
+ }
+ else if (obj instanceof DERConstructedSet)
+ {
+ StringBuffer buf = new StringBuffer();
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("ConstructedSet");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ buf.append(_dumpAsString(tab, verbose, (DERObject)o));
+ }
+ else
+ {
+ buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject()));
+ }
+ }
+ return buf.toString();
+ }
+ else if (obj instanceof BERSet)
+ {
+ StringBuffer buf = new StringBuffer();
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("BER Set");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ buf.append(_dumpAsString(tab, verbose, (DERObject)o));
+ }
+ else
+ {
+ buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject()));
+ }
+ }
+ return buf.toString();
+ }
+ else if (obj instanceof DERSet)
+ {
+ StringBuffer buf = new StringBuffer();
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ buf.append("DER Set");
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof DERObject)
+ {
+ buf.append(_dumpAsString(tab, verbose, (DERObject)o));
+ }
+ else
+ {
+ buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject()));
+ }
+ }
+ return buf.toString();
+ }
+ else if (obj instanceof DERObjectIdentifier)
+ {
+ return indent + "ObjectIdentifier(" + ((DERObjectIdentifier)obj).getId() + ")" + nl;
+ }
+ else if (obj instanceof DERBoolean)
+ {
+ return indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl;
+ }
+ else if (obj instanceof DERInteger)
+ {
+ return indent + "Integer(" + ((DERInteger)obj).getValue() + ")" + nl;
+ }
+ else if (obj instanceof BERConstructedOctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+ if (verbose)
+ {
+ return indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] " + dumpBinaryDataAsString(indent, oct.getOctets()) + nl;
+ }
+ return indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] " + nl;
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+ if (verbose)
+ {
+ return indent + "DER Octet String" + "[" + oct.getOctets().length + "] " + dumpBinaryDataAsString(indent, oct.getOctets()) + nl;
+ }
+ return indent + "DER Octet String" + "[" + oct.getOctets().length + "] " + nl;
+ }
+ else if (obj instanceof DERBitString)
+ {
+ DERBitString bt = (DERBitString)obj;
+ if (verbose)
+ {
+ return indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] " + dumpBinaryDataAsString(indent, bt.getBytes()) + nl;
+ }
+ return indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] " + nl;
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ return indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ return indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERPrintableString)
+ {
+ return indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERVisibleString)
+ {
+ return indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERBMPString)
+ {
+ return indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERT61String)
+ {
+ return indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl;
+ }
+ else if (obj instanceof DERUTCTime)
+ {
+ return indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl;
+ }
+ else if (obj instanceof DERGeneralizedTime)
+ {
+ return indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl;
+ }
+ else if (obj instanceof DERUnknownTag)
+ {
+ return indent + "Unknown " + Integer.toString(((DERUnknownTag)obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag)obj).getData())) + nl;
+ }
+ else if (obj instanceof BERApplicationSpecific)
+ {
+ return outputApplicationSpecific("BER", indent, verbose, obj, nl);
+ }
+ else if (obj instanceof DERApplicationSpecific)
+ {
+ return outputApplicationSpecific("DER", indent, verbose, obj, nl);
+ }
+ else
+ {
+ return indent + obj.toString() + nl;
+ }
+ }
+
+ private static String outputApplicationSpecific(String type, String indent, boolean verbose, DERObject obj, String nl)
+ {
+ DERApplicationSpecific app = (DERApplicationSpecific)obj;
+ StringBuffer buf = new StringBuffer();
+
+ if (app.isConstructed())
+ {
+ try
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(DERTags.SEQUENCE));
+ buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
+ for (Enumeration e = s.getObjects(); e.hasMoreElements();)
+ {
+ buf.append(_dumpAsString(indent + TAB, verbose, (DERObject)e.nextElement()));
+ }
+ }
+ catch (IOException e)
+ {
+ buf.append(e);
+ }
+ return buf.toString();
+ }
+
+ return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
+ }
+
+ /**
+ * dump out a DER object as a formatted string, in non-verbose mode.
+ *
+ * @param obj the DERObject to be dumped out.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj)
+ {
+ return dumpAsString(obj, false);
+ }
+
+ /**
+ * Dump out the object as a string.
+ *
+ * @param obj the object to be dumped
+ * @param verbose if true, dump out the contents of octet and bit strings.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj,
+ boolean verbose)
+ {
+ if (obj instanceof DERObject)
+ {
+ return _dumpAsString("", verbose, (DERObject)obj);
+ }
+ else if (obj instanceof DEREncodable)
+ {
+ return _dumpAsString("", verbose, ((DEREncodable)obj).getDERObject());
+ }
+
+ return "unknown object type " + obj.toString();
+ }
+
+ private static String dumpBinaryDataAsString(String indent, byte[] bytes)
+ {
+ String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ indent += TAB;
+
+ buf.append(nl);
+ for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
+ {
+ if (bytes.length - i > SAMPLE_SIZE)
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
+ buf.append(nl);
+ }
+ else
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
+ for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
+ {
+ buf.append(" ");
+ }
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, bytes.length - i));
+ buf.append(nl);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static String calculateAscString(byte[] bytes, int off, int len)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ for (int i = off; i != off + len; i++)
+ {
+ if (bytes[i] >= ' ' && bytes[i] <= '~')
+ {
+ buf.append((char)bytes[i]);
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/DERDump.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/DERDump.java
new file mode 100644
index 00000000..943cd2b5
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/DERDump.java
@@ -0,0 +1,41 @@
+package org.bouncycastle.asn1.util;
+
+import org.bouncycastle.asn1.DEREncodable;
+import org.bouncycastle.asn1.DERObject;
+
+/**
+ * @deprecated use ASN1Dump.
+ */
+public class DERDump
+ extends ASN1Dump
+{
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the DERObject to be dumped out.
+ */
+ public static String dumpAsString(
+ DERObject obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj, buf);
+
+ return buf.toString();
+ }
+
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the DERObject to be dumped out.
+ */
+ public static String dumpAsString(
+ DEREncodable obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj.getDERObject(), buf);
+
+ return buf.toString();
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/Dump.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/Dump.java
new file mode 100644
index 00000000..27a37f34
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/asn1/util/Dump.java
@@ -0,0 +1,22 @@
+package org.bouncycastle.asn1.util;
+
+import java.io.FileInputStream;
+
+import org.bouncycastle.asn1.ASN1InputStream;
+
+public class Dump
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ FileInputStream fIn = new FileInputStream(args[0]);
+ ASN1InputStream bIn = new ASN1InputStream(fIn);
+ Object obj = null;
+
+ while ((obj = bIn.readObject()) != null)
+ {
+ System.out.println(ASN1Dump.dumpAsString(obj));
+ }
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BlockCipher.java
new file mode 100644
index 00000000..3cfa25a0
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BlockCipher.java
@@ -0,0 +1,56 @@
+package org.bouncycastle.crypto;
+
+
+/**
+ * Block cipher engines are expected to conform to this interface.
+ */
+public interface BlockCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this cipher (in bytes).
+ *
+ * @return the block size for this cipher in bytes.
+ */
+ public int getBlockSize();
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BufferedBlockCipher.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BufferedBlockCipher.java
new file mode 100644
index 00000000..7f8adec7
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -0,0 +1,307 @@
+package org.bouncycastle.crypto;
+
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+ * buffer is full and more data is being added, or on a doFinal.
+ *
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ *
+ */
+public class SHA256Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private int H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private int[] X = new int[64];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA256Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA256Digest(SHA256Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-256";
+ }
+
+ 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);
+ Pack.intToBigEndian(H6, out, outOff + 20);
+ Pack.intToBigEndian(H7, out, outOff + 24);
+ Pack.intToBigEndian(H8, out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-256 initial hash value
+ * The first 32 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+
+ H1 = 0x6a09e667;
+ H2 = 0xbb67ae85;
+ H3 = 0x3c6ef372;
+ H4 = 0xa54ff53a;
+ H5 = 0x510e527f;
+ H6 = 0x9b05688c;
+ H7 = 0x1f83d9ab;
+ H8 = 0x5be0cd19;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int t = 16; t <= 63; t++)
+ {
+ X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+ int e = H5;
+ int f = H6;
+ int g = H7;
+ int h = H8;
+
+ int t = 0;
+ for(int i = 0; i < 8; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /* SHA-256 functions */
+ private int Ch(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ ((~x) & z);
+ }
+
+ private int Maj(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ (x & z) ^ (y & z);
+ }
+
+ private int Sum0(
+ int x)
+ {
+ return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
+ }
+
+ private int Sum1(
+ int x)
+ {
+ return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
+ }
+
+ private int Theta0(
+ int x)
+ {
+ return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
+ }
+
+ private int Theta1(
+ int x)
+ {
+ return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
+ }
+
+ /* SHA-256 Constants
+ * (represent the first 32 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final int K[] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+}
+
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/TigerDigest.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/TigerDigest.java
new file mode 100644
index 00000000..0062ea92
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/digests/TigerDigest.java
@@ -0,0 +1,866 @@
+package org.bouncycastle.crypto.digests;
+
+import org.bouncycastle.crypto.ExtendedDigest;
+
+/**
+ * implementation of Tiger based on:
+ *
+ * http://www.cs.technion.ac.il/~biham/Reports/Tiger
+ */
+public class TigerDigest
+ implements ExtendedDigest
+{
+ private static final int BYTE_LENGTH = 64;
+
+ /*
+ * S-Boxes.
+ */
+ private static final long[] t1 = {
+ 0x02AAB17CF7E90C5EL /* 0 */, 0xAC424B03E243A8ECL /* 1 */,
+ 0x72CD5BE30DD5FCD3L /* 2 */, 0x6D019B93F6F97F3AL /* 3 */,
+ 0xCD9978FFD21F9193L /* 4 */, 0x7573A1C9708029E2L /* 5 */,
+ 0xB164326B922A83C3L /* 6 */, 0x46883EEE04915870L /* 7 */,
+ 0xEAACE3057103ECE6L /* 8 */, 0xC54169B808A3535CL /* 9 */,
+ 0x4CE754918DDEC47CL /* 10 */, 0x0AA2F4DFDC0DF40CL /* 11 */,
+ 0x10B76F18A74DBEFAL /* 12 */, 0xC6CCB6235AD1AB6AL /* 13 */,
+ 0x13726121572FE2FFL /* 14 */, 0x1A488C6F199D921EL /* 15 */,
+ 0x4BC9F9F4DA0007CAL /* 16 */, 0x26F5E6F6E85241C7L /* 17 */,
+ 0x859079DBEA5947B6L /* 18 */, 0x4F1885C5C99E8C92L /* 19 */,
+ 0xD78E761EA96F864BL /* 20 */, 0x8E36428C52B5C17DL /* 21 */,
+ 0x69CF6827373063C1L /* 22 */, 0xB607C93D9BB4C56EL /* 23 */,
+ 0x7D820E760E76B5EAL /* 24 */, 0x645C9CC6F07FDC42L /* 25 */,
+ 0xBF38A078243342E0L /* 26 */, 0x5F6B343C9D2E7D04L /* 27 */,
+ 0xF2C28AEB600B0EC6L /* 28 */, 0x6C0ED85F7254BCACL /* 29 */,
+ 0x71592281A4DB4FE5L /* 30 */, 0x1967FA69CE0FED9FL /* 31 */,
+ 0xFD5293F8B96545DBL /* 32 */, 0xC879E9D7F2A7600BL /* 33 */,
+ 0x860248920193194EL /* 34 */, 0xA4F9533B2D9CC0B3L /* 35 */,
+ 0x9053836C15957613L /* 36 */, 0xDB6DCF8AFC357BF1L /* 37 */,
+ 0x18BEEA7A7A370F57L /* 38 */, 0x037117CA50B99066L /* 39 */,
+ 0x6AB30A9774424A35L /* 40 */, 0xF4E92F02E325249BL /* 41 */,
+ 0x7739DB07061CCAE1L /* 42 */, 0xD8F3B49CECA42A05L /* 43 */,
+ 0xBD56BE3F51382F73L /* 44 */, 0x45FAED5843B0BB28L /* 45 */,
+ 0x1C813D5C11BF1F83L /* 46 */, 0x8AF0E4B6D75FA169L /* 47 */,
+ 0x33EE18A487AD9999L /* 48 */, 0x3C26E8EAB1C94410L /* 49 */,
+ 0xB510102BC0A822F9L /* 50 */, 0x141EEF310CE6123BL /* 51 */,
+ 0xFC65B90059DDB154L /* 52 */, 0xE0158640C5E0E607L /* 53 */,
+ 0x884E079826C3A3CFL /* 54 */, 0x930D0D9523C535FDL /* 55 */,
+ 0x35638D754E9A2B00L /* 56 */, 0x4085FCCF40469DD5L /* 57 */,
+ 0xC4B17AD28BE23A4CL /* 58 */, 0xCAB2F0FC6A3E6A2EL /* 59 */,
+ 0x2860971A6B943FCDL /* 60 */, 0x3DDE6EE212E30446L /* 61 */,
+ 0x6222F32AE01765AEL /* 62 */, 0x5D550BB5478308FEL /* 63 */,
+ 0xA9EFA98DA0EDA22AL /* 64 */, 0xC351A71686C40DA7L /* 65 */,
+ 0x1105586D9C867C84L /* 66 */, 0xDCFFEE85FDA22853L /* 67 */,
+ 0xCCFBD0262C5EEF76L /* 68 */, 0xBAF294CB8990D201L /* 69 */,
+ 0xE69464F52AFAD975L /* 70 */, 0x94B013AFDF133E14L /* 71 */,
+ 0x06A7D1A32823C958L /* 72 */, 0x6F95FE5130F61119L /* 73 */,
+ 0xD92AB34E462C06C0L /* 74 */, 0xED7BDE33887C71D2L /* 75 */,
+ 0x79746D6E6518393EL /* 76 */, 0x5BA419385D713329L /* 77 */,
+ 0x7C1BA6B948A97564L /* 78 */, 0x31987C197BFDAC67L /* 79 */,
+ 0xDE6C23C44B053D02L /* 80 */, 0x581C49FED002D64DL /* 81 */,
+ 0xDD474D6338261571L /* 82 */, 0xAA4546C3E473D062L /* 83 */,
+ 0x928FCE349455F860L /* 84 */, 0x48161BBACAAB94D9L /* 85 */,
+ 0x63912430770E6F68L /* 86 */, 0x6EC8A5E602C6641CL /* 87 */,
+ 0x87282515337DDD2BL /* 88 */, 0x2CDA6B42034B701BL /* 89 */,
+ 0xB03D37C181CB096DL /* 90 */, 0xE108438266C71C6FL /* 91 */,
+ 0x2B3180C7EB51B255L /* 92 */, 0xDF92B82F96C08BBCL /* 93 */,
+ 0x5C68C8C0A632F3BAL /* 94 */, 0x5504CC861C3D0556L /* 95 */,
+ 0xABBFA4E55FB26B8FL /* 96 */, 0x41848B0AB3BACEB4L /* 97 */,
+ 0xB334A273AA445D32L /* 98 */, 0xBCA696F0A85AD881L /* 99 */,
+ 0x24F6EC65B528D56CL /* 100 */, 0x0CE1512E90F4524AL /* 101 */,
+ 0x4E9DD79D5506D35AL /* 102 */, 0x258905FAC6CE9779L /* 103 */,
+ 0x2019295B3E109B33L /* 104 */, 0xF8A9478B73A054CCL /* 105 */,
+ 0x2924F2F934417EB0L /* 106 */, 0x3993357D536D1BC4L /* 107 */,
+ 0x38A81AC21DB6FF8BL /* 108 */, 0x47C4FBF17D6016BFL /* 109 */,
+ 0x1E0FAADD7667E3F5L /* 110 */, 0x7ABCFF62938BEB96L /* 111 */,
+ 0xA78DAD948FC179C9L /* 112 */, 0x8F1F98B72911E50DL /* 113 */,
+ 0x61E48EAE27121A91L /* 114 */, 0x4D62F7AD31859808L /* 115 */,
+ 0xECEBA345EF5CEAEBL /* 116 */, 0xF5CEB25EBC9684CEL /* 117 */,
+ 0xF633E20CB7F76221L /* 118 */, 0xA32CDF06AB8293E4L /* 119 */,
+ 0x985A202CA5EE2CA4L /* 120 */, 0xCF0B8447CC8A8FB1L /* 121 */,
+ 0x9F765244979859A3L /* 122 */, 0xA8D516B1A1240017L /* 123 */,
+ 0x0BD7BA3EBB5DC726L /* 124 */, 0xE54BCA55B86ADB39L /* 125 */,
+ 0x1D7A3AFD6C478063L /* 126 */, 0x519EC608E7669EDDL /* 127 */,
+ 0x0E5715A2D149AA23L /* 128 */, 0x177D4571848FF194L /* 129 */,
+ 0xEEB55F3241014C22L /* 130 */, 0x0F5E5CA13A6E2EC2L /* 131 */,
+ 0x8029927B75F5C361L /* 132 */, 0xAD139FABC3D6E436L /* 133 */,
+ 0x0D5DF1A94CCF402FL /* 134 */, 0x3E8BD948BEA5DFC8L /* 135 */,
+ 0xA5A0D357BD3FF77EL /* 136 */, 0xA2D12E251F74F645L /* 137 */,
+ 0x66FD9E525E81A082L /* 138 */, 0x2E0C90CE7F687A49L /* 139 */,
+ 0xC2E8BCBEBA973BC5L /* 140 */, 0x000001BCE509745FL /* 141 */,
+ 0x423777BBE6DAB3D6L /* 142 */, 0xD1661C7EAEF06EB5L /* 143 */,
+ 0xA1781F354DAACFD8L /* 144 */, 0x2D11284A2B16AFFCL /* 145 */,
+ 0xF1FC4F67FA891D1FL /* 146 */, 0x73ECC25DCB920ADAL /* 147 */,
+ 0xAE610C22C2A12651L /* 148 */, 0x96E0A810D356B78AL /* 149 */,
+ 0x5A9A381F2FE7870FL /* 150 */, 0xD5AD62EDE94E5530L /* 151 */,
+ 0xD225E5E8368D1427L /* 152 */, 0x65977B70C7AF4631L /* 153 */,
+ 0x99F889B2DE39D74FL /* 154 */, 0x233F30BF54E1D143L /* 155 */,
+ 0x9A9675D3D9A63C97L /* 156 */, 0x5470554FF334F9A8L /* 157 */,
+ 0x166ACB744A4F5688L /* 158 */, 0x70C74CAAB2E4AEADL /* 159 */,
+ 0xF0D091646F294D12L /* 160 */, 0x57B82A89684031D1L /* 161 */,
+ 0xEFD95A5A61BE0B6BL /* 162 */, 0x2FBD12E969F2F29AL /* 163 */,
+ 0x9BD37013FEFF9FE8L /* 164 */, 0x3F9B0404D6085A06L /* 165 */,
+ 0x4940C1F3166CFE15L /* 166 */, 0x09542C4DCDF3DEFBL /* 167 */,
+ 0xB4C5218385CD5CE3L /* 168 */, 0xC935B7DC4462A641L /* 169 */,
+ 0x3417F8A68ED3B63FL /* 170 */, 0xB80959295B215B40L /* 171 */,
+ 0xF99CDAEF3B8C8572L /* 172 */, 0x018C0614F8FCB95DL /* 173 */,
+ 0x1B14ACCD1A3ACDF3L /* 174 */, 0x84D471F200BB732DL /* 175 */,
+ 0xC1A3110E95E8DA16L /* 176 */, 0x430A7220BF1A82B8L /* 177 */,
+ 0xB77E090D39DF210EL /* 178 */, 0x5EF4BD9F3CD05E9DL /* 179 */,
+ 0x9D4FF6DA7E57A444L /* 180 */, 0xDA1D60E183D4A5F8L /* 181 */,
+ 0xB287C38417998E47L /* 182 */, 0xFE3EDC121BB31886L /* 183 */,
+ 0xC7FE3CCC980CCBEFL /* 184 */, 0xE46FB590189BFD03L /* 185 */,
+ 0x3732FD469A4C57DCL /* 186 */, 0x7EF700A07CF1AD65L /* 187 */,
+ 0x59C64468A31D8859L /* 188 */, 0x762FB0B4D45B61F6L /* 189 */,
+ 0x155BAED099047718L /* 190 */, 0x68755E4C3D50BAA6L /* 191 */,
+ 0xE9214E7F22D8B4DFL /* 192 */, 0x2ADDBF532EAC95F4L /* 193 */,
+ 0x32AE3909B4BD0109L /* 194 */, 0x834DF537B08E3450L /* 195 */,
+ 0xFA209DA84220728DL /* 196 */, 0x9E691D9B9EFE23F7L /* 197 */,
+ 0x0446D288C4AE8D7FL /* 198 */, 0x7B4CC524E169785BL /* 199 */,
+ 0x21D87F0135CA1385L /* 200 */, 0xCEBB400F137B8AA5L /* 201 */,
+ 0x272E2B66580796BEL /* 202 */, 0x3612264125C2B0DEL /* 203 */,
+ 0x057702BDAD1EFBB2L /* 204 */, 0xD4BABB8EACF84BE9L /* 205 */,
+ 0x91583139641BC67BL /* 206 */, 0x8BDC2DE08036E024L /* 207 */,
+ 0x603C8156F49F68EDL /* 208 */, 0xF7D236F7DBEF5111L /* 209 */,
+ 0x9727C4598AD21E80L /* 210 */, 0xA08A0896670A5FD7L /* 211 */,
+ 0xCB4A8F4309EBA9CBL /* 212 */, 0x81AF564B0F7036A1L /* 213 */,
+ 0xC0B99AA778199ABDL /* 214 */, 0x959F1EC83FC8E952L /* 215 */,
+ 0x8C505077794A81B9L /* 216 */, 0x3ACAAF8F056338F0L /* 217 */,
+ 0x07B43F50627A6778L /* 218 */, 0x4A44AB49F5ECCC77L /* 219 */,
+ 0x3BC3D6E4B679EE98L /* 220 */, 0x9CC0D4D1CF14108CL /* 221 */,
+ 0x4406C00B206BC8A0L /* 222 */, 0x82A18854C8D72D89L /* 223 */,
+ 0x67E366B35C3C432CL /* 224 */, 0xB923DD61102B37F2L /* 225 */,
+ 0x56AB2779D884271DL /* 226 */, 0xBE83E1B0FF1525AFL /* 227 */,
+ 0xFB7C65D4217E49A9L /* 228 */, 0x6BDBE0E76D48E7D4L /* 229 */,
+ 0x08DF828745D9179EL /* 230 */, 0x22EA6A9ADD53BD34L /* 231 */,
+ 0xE36E141C5622200AL /* 232 */, 0x7F805D1B8CB750EEL /* 233 */,
+ 0xAFE5C7A59F58E837L /* 234 */, 0xE27F996A4FB1C23CL /* 235 */,
+ 0xD3867DFB0775F0D0L /* 236 */, 0xD0E673DE6E88891AL /* 237 */,
+ 0x123AEB9EAFB86C25L /* 238 */, 0x30F1D5D5C145B895L /* 239 */,
+ 0xBB434A2DEE7269E7L /* 240 */, 0x78CB67ECF931FA38L /* 241 */,
+ 0xF33B0372323BBF9CL /* 242 */, 0x52D66336FB279C74L /* 243 */,
+ 0x505F33AC0AFB4EAAL /* 244 */, 0xE8A5CD99A2CCE187L /* 245 */,
+ 0x534974801E2D30BBL /* 246 */, 0x8D2D5711D5876D90L /* 247 */,
+ 0x1F1A412891BC038EL /* 248 */, 0xD6E2E71D82E56648L /* 249 */,
+ 0x74036C3A497732B7L /* 250 */, 0x89B67ED96361F5ABL /* 251 */,
+ 0xFFED95D8F1EA02A2L /* 252 */, 0xE72B3BD61464D43DL /* 253 */,
+ 0xA6300F170BDC4820L /* 254 */, 0xEBC18760ED78A77AL /* 255 */,
+ };
+
+ private static final long[] t2 = {
+ 0xE6A6BE5A05A12138L /* 256 */, 0xB5A122A5B4F87C98L /* 257 */,
+ 0x563C6089140B6990L /* 258 */, 0x4C46CB2E391F5DD5L /* 259 */,
+ 0xD932ADDBC9B79434L /* 260 */, 0x08EA70E42015AFF5L /* 261 */,
+ 0xD765A6673E478CF1L /* 262 */, 0xC4FB757EAB278D99L /* 263 */,
+ 0xDF11C6862D6E0692L /* 264 */, 0xDDEB84F10D7F3B16L /* 265 */,
+ 0x6F2EF604A665EA04L /* 266 */, 0x4A8E0F0FF0E0DFB3L /* 267 */,
+ 0xA5EDEEF83DBCBA51L /* 268 */, 0xFC4F0A2A0EA4371EL /* 269 */,
+ 0xE83E1DA85CB38429L /* 270 */, 0xDC8FF882BA1B1CE2L /* 271 */,
+ 0xCD45505E8353E80DL /* 272 */, 0x18D19A00D4DB0717L /* 273 */,
+ 0x34A0CFEDA5F38101L /* 274 */, 0x0BE77E518887CAF2L /* 275 */,
+ 0x1E341438B3C45136L /* 276 */, 0xE05797F49089CCF9L /* 277 */,
+ 0xFFD23F9DF2591D14L /* 278 */, 0x543DDA228595C5CDL /* 279 */,
+ 0x661F81FD99052A33L /* 280 */, 0x8736E641DB0F7B76L /* 281 */,
+ 0x15227725418E5307L /* 282 */, 0xE25F7F46162EB2FAL /* 283 */,
+ 0x48A8B2126C13D9FEL /* 284 */, 0xAFDC541792E76EEAL /* 285 */,
+ 0x03D912BFC6D1898FL /* 286 */, 0x31B1AAFA1B83F51BL /* 287 */,
+ 0xF1AC2796E42AB7D9L /* 288 */, 0x40A3A7D7FCD2EBACL /* 289 */,
+ 0x1056136D0AFBBCC5L /* 290 */, 0x7889E1DD9A6D0C85L /* 291 */,
+ 0xD33525782A7974AAL /* 292 */, 0xA7E25D09078AC09BL /* 293 */,
+ 0xBD4138B3EAC6EDD0L /* 294 */, 0x920ABFBE71EB9E70L /* 295 */,
+ 0xA2A5D0F54FC2625CL /* 296 */, 0xC054E36B0B1290A3L /* 297 */,
+ 0xF6DD59FF62FE932BL /* 298 */, 0x3537354511A8AC7DL /* 299 */,
+ 0xCA845E9172FADCD4L /* 300 */, 0x84F82B60329D20DCL /* 301 */,
+ 0x79C62CE1CD672F18L /* 302 */, 0x8B09A2ADD124642CL /* 303 */,
+ 0xD0C1E96A19D9E726L /* 304 */, 0x5A786A9B4BA9500CL /* 305 */,
+ 0x0E020336634C43F3L /* 306 */, 0xC17B474AEB66D822L /* 307 */,
+ 0x6A731AE3EC9BAAC2L /* 308 */, 0x8226667AE0840258L /* 309 */,
+ 0x67D4567691CAECA5L /* 310 */, 0x1D94155C4875ADB5L /* 311 */,
+ 0x6D00FD985B813FDFL /* 312 */, 0x51286EFCB774CD06L /* 313 */,
+ 0x5E8834471FA744AFL /* 314 */, 0xF72CA0AEE761AE2EL /* 315 */,
+ 0xBE40E4CDAEE8E09AL /* 316 */, 0xE9970BBB5118F665L /* 317 */,
+ 0x726E4BEB33DF1964L /* 318 */, 0x703B000729199762L /* 319 */,
+ 0x4631D816F5EF30A7L /* 320 */, 0xB880B5B51504A6BEL /* 321 */,
+ 0x641793C37ED84B6CL /* 322 */, 0x7B21ED77F6E97D96L /* 323 */,
+ 0x776306312EF96B73L /* 324 */, 0xAE528948E86FF3F4L /* 325 */,
+ 0x53DBD7F286A3F8F8L /* 326 */, 0x16CADCE74CFC1063L /* 327 */,
+ 0x005C19BDFA52C6DDL /* 328 */, 0x68868F5D64D46AD3L /* 329 */,
+ 0x3A9D512CCF1E186AL /* 330 */, 0x367E62C2385660AEL /* 331 */,
+ 0xE359E7EA77DCB1D7L /* 332 */, 0x526C0773749ABE6EL /* 333 */,
+ 0x735AE5F9D09F734BL /* 334 */, 0x493FC7CC8A558BA8L /* 335 */,
+ 0xB0B9C1533041AB45L /* 336 */, 0x321958BA470A59BDL /* 337 */,
+ 0x852DB00B5F46C393L /* 338 */, 0x91209B2BD336B0E5L /* 339 */,
+ 0x6E604F7D659EF19FL /* 340 */, 0xB99A8AE2782CCB24L /* 341 */,
+ 0xCCF52AB6C814C4C7L /* 342 */, 0x4727D9AFBE11727BL /* 343 */,
+ 0x7E950D0C0121B34DL /* 344 */, 0x756F435670AD471FL /* 345 */,
+ 0xF5ADD442615A6849L /* 346 */, 0x4E87E09980B9957AL /* 347 */,
+ 0x2ACFA1DF50AEE355L /* 348 */, 0xD898263AFD2FD556L /* 349 */,
+ 0xC8F4924DD80C8FD6L /* 350 */, 0xCF99CA3D754A173AL /* 351 */,
+ 0xFE477BACAF91BF3CL /* 352 */, 0xED5371F6D690C12DL /* 353 */,
+ 0x831A5C285E687094L /* 354 */, 0xC5D3C90A3708A0A4L /* 355 */,
+ 0x0F7F903717D06580L /* 356 */, 0x19F9BB13B8FDF27FL /* 357 */,
+ 0xB1BD6F1B4D502843L /* 358 */, 0x1C761BA38FFF4012L /* 359 */,
+ 0x0D1530C4E2E21F3BL /* 360 */, 0x8943CE69A7372C8AL /* 361 */,
+ 0xE5184E11FEB5CE66L /* 362 */, 0x618BDB80BD736621L /* 363 */,
+ 0x7D29BAD68B574D0BL /* 364 */, 0x81BB613E25E6FE5BL /* 365 */,
+ 0x071C9C10BC07913FL /* 366 */, 0xC7BEEB7909AC2D97L /* 367 */,
+ 0xC3E58D353BC5D757L /* 368 */, 0xEB017892F38F61E8L /* 369 */,
+ 0xD4EFFB9C9B1CC21AL /* 370 */, 0x99727D26F494F7ABL /* 371 */,
+ 0xA3E063A2956B3E03L /* 372 */, 0x9D4A8B9A4AA09C30L /* 373 */,
+ 0x3F6AB7D500090FB4L /* 374 */, 0x9CC0F2A057268AC0L /* 375 */,
+ 0x3DEE9D2DEDBF42D1L /* 376 */, 0x330F49C87960A972L /* 377 */,
+ 0xC6B2720287421B41L /* 378 */, 0x0AC59EC07C00369CL /* 379 */,
+ 0xEF4EAC49CB353425L /* 380 */, 0xF450244EEF0129D8L /* 381 */,
+ 0x8ACC46E5CAF4DEB6L /* 382 */, 0x2FFEAB63989263F7L /* 383 */,
+ 0x8F7CB9FE5D7A4578L /* 384 */, 0x5BD8F7644E634635L /* 385 */,
+ 0x427A7315BF2DC900L /* 386 */, 0x17D0C4AA2125261CL /* 387 */,
+ 0x3992486C93518E50L /* 388 */, 0xB4CBFEE0A2D7D4C3L /* 389 */,
+ 0x7C75D6202C5DDD8DL /* 390 */, 0xDBC295D8E35B6C61L /* 391 */,
+ 0x60B369D302032B19L /* 392 */, 0xCE42685FDCE44132L /* 393 */,
+ 0x06F3DDB9DDF65610L /* 394 */, 0x8EA4D21DB5E148F0L /* 395 */,
+ 0x20B0FCE62FCD496FL /* 396 */, 0x2C1B912358B0EE31L /* 397 */,
+ 0xB28317B818F5A308L /* 398 */, 0xA89C1E189CA6D2CFL /* 399 */,
+ 0x0C6B18576AAADBC8L /* 400 */, 0xB65DEAA91299FAE3L /* 401 */,
+ 0xFB2B794B7F1027E7L /* 402 */, 0x04E4317F443B5BEBL /* 403 */,
+ 0x4B852D325939D0A6L /* 404 */, 0xD5AE6BEEFB207FFCL /* 405 */,
+ 0x309682B281C7D374L /* 406 */, 0xBAE309A194C3B475L /* 407 */,
+ 0x8CC3F97B13B49F05L /* 408 */, 0x98A9422FF8293967L /* 409 */,
+ 0x244B16B01076FF7CL /* 410 */, 0xF8BF571C663D67EEL /* 411 */,
+ 0x1F0D6758EEE30DA1L /* 412 */, 0xC9B611D97ADEB9B7L /* 413 */,
+ 0xB7AFD5887B6C57A2L /* 414 */, 0x6290AE846B984FE1L /* 415 */,
+ 0x94DF4CDEACC1A5FDL /* 416 */, 0x058A5BD1C5483AFFL /* 417 */,
+ 0x63166CC142BA3C37L /* 418 */, 0x8DB8526EB2F76F40L /* 419 */,
+ 0xE10880036F0D6D4EL /* 420 */, 0x9E0523C9971D311DL /* 421 */,
+ 0x45EC2824CC7CD691L /* 422 */, 0x575B8359E62382C9L /* 423 */,
+ 0xFA9E400DC4889995L /* 424 */, 0xD1823ECB45721568L /* 425 */,
+ 0xDAFD983B8206082FL /* 426 */, 0xAA7D29082386A8CBL /* 427 */,
+ 0x269FCD4403B87588L /* 428 */, 0x1B91F5F728BDD1E0L /* 429 */,
+ 0xE4669F39040201F6L /* 430 */, 0x7A1D7C218CF04ADEL /* 431 */,
+ 0x65623C29D79CE5CEL /* 432 */, 0x2368449096C00BB1L /* 433 */,
+ 0xAB9BF1879DA503BAL /* 434 */, 0xBC23ECB1A458058EL /* 435 */,
+ 0x9A58DF01BB401ECCL /* 436 */, 0xA070E868A85F143DL /* 437 */,
+ 0x4FF188307DF2239EL /* 438 */, 0x14D565B41A641183L /* 439 */,
+ 0xEE13337452701602L /* 440 */, 0x950E3DCF3F285E09L /* 441 */,
+ 0x59930254B9C80953L /* 442 */, 0x3BF299408930DA6DL /* 443 */,
+ 0xA955943F53691387L /* 444 */, 0xA15EDECAA9CB8784L /* 445 */,
+ 0x29142127352BE9A0L /* 446 */, 0x76F0371FFF4E7AFBL /* 447 */,
+ 0x0239F450274F2228L /* 448 */, 0xBB073AF01D5E868BL /* 449 */,
+ 0xBFC80571C10E96C1L /* 450 */, 0xD267088568222E23L /* 451 */,
+ 0x9671A3D48E80B5B0L /* 452 */, 0x55B5D38AE193BB81L /* 453 */,
+ 0x693AE2D0A18B04B8L /* 454 */, 0x5C48B4ECADD5335FL /* 455 */,
+ 0xFD743B194916A1CAL /* 456 */, 0x2577018134BE98C4L /* 457 */,
+ 0xE77987E83C54A4ADL /* 458 */, 0x28E11014DA33E1B9L /* 459 */,
+ 0x270CC59E226AA213L /* 460 */, 0x71495F756D1A5F60L /* 461 */,
+ 0x9BE853FB60AFEF77L /* 462 */, 0xADC786A7F7443DBFL /* 463 */,
+ 0x0904456173B29A82L /* 464 */, 0x58BC7A66C232BD5EL /* 465 */,
+ 0xF306558C673AC8B2L /* 466 */, 0x41F639C6B6C9772AL /* 467 */,
+ 0x216DEFE99FDA35DAL /* 468 */, 0x11640CC71C7BE615L /* 469 */,
+ 0x93C43694565C5527L /* 470 */, 0xEA038E6246777839L /* 471 */,
+ 0xF9ABF3CE5A3E2469L /* 472 */, 0x741E768D0FD312D2L /* 473 */,
+ 0x0144B883CED652C6L /* 474 */, 0xC20B5A5BA33F8552L /* 475 */,
+ 0x1AE69633C3435A9DL /* 476 */, 0x97A28CA4088CFDECL /* 477 */,
+ 0x8824A43C1E96F420L /* 478 */, 0x37612FA66EEEA746L /* 479 */,
+ 0x6B4CB165F9CF0E5AL /* 480 */, 0x43AA1C06A0ABFB4AL /* 481 */,
+ 0x7F4DC26FF162796BL /* 482 */, 0x6CBACC8E54ED9B0FL /* 483 */,
+ 0xA6B7FFEFD2BB253EL /* 484 */, 0x2E25BC95B0A29D4FL /* 485 */,
+ 0x86D6A58BDEF1388CL /* 486 */, 0xDED74AC576B6F054L /* 487 */,
+ 0x8030BDBC2B45805DL /* 488 */, 0x3C81AF70E94D9289L /* 489 */,
+ 0x3EFF6DDA9E3100DBL /* 490 */, 0xB38DC39FDFCC8847L /* 491 */,
+ 0x123885528D17B87EL /* 492 */, 0xF2DA0ED240B1B642L /* 493 */,
+ 0x44CEFADCD54BF9A9L /* 494 */, 0x1312200E433C7EE6L /* 495 */,
+ 0x9FFCC84F3A78C748L /* 496 */, 0xF0CD1F72248576BBL /* 497 */,
+ 0xEC6974053638CFE4L /* 498 */, 0x2BA7B67C0CEC4E4CL /* 499 */,
+ 0xAC2F4DF3E5CE32EDL /* 500 */, 0xCB33D14326EA4C11L /* 501 */,
+ 0xA4E9044CC77E58BCL /* 502 */, 0x5F513293D934FCEFL /* 503 */,
+ 0x5DC9645506E55444L /* 504 */, 0x50DE418F317DE40AL /* 505 */,
+ 0x388CB31A69DDE259L /* 506 */, 0x2DB4A83455820A86L /* 507 */,
+ 0x9010A91E84711AE9L /* 508 */, 0x4DF7F0B7B1498371L /* 509 */,
+ 0xD62A2EABC0977179L /* 510 */, 0x22FAC097AA8D5C0EL /* 511 */,
+ };
+
+ private static final long[] t3 = {
+ 0xF49FCC2FF1DAF39BL /* 512 */, 0x487FD5C66FF29281L /* 513 */,
+ 0xE8A30667FCDCA83FL /* 514 */, 0x2C9B4BE3D2FCCE63L /* 515 */,
+ 0xDA3FF74B93FBBBC2L /* 516 */, 0x2FA165D2FE70BA66L /* 517 */,
+ 0xA103E279970E93D4L /* 518 */, 0xBECDEC77B0E45E71L /* 519 */,
+ 0xCFB41E723985E497L /* 520 */, 0xB70AAA025EF75017L /* 521 */,
+ 0xD42309F03840B8E0L /* 522 */, 0x8EFC1AD035898579L /* 523 */,
+ 0x96C6920BE2B2ABC5L /* 524 */, 0x66AF4163375A9172L /* 525 */,
+ 0x2174ABDCCA7127FBL /* 526 */, 0xB33CCEA64A72FF41L /* 527 */,
+ 0xF04A4933083066A5L /* 528 */, 0x8D970ACDD7289AF5L /* 529 */,
+ 0x8F96E8E031C8C25EL /* 530 */, 0xF3FEC02276875D47L /* 531 */,
+ 0xEC7BF310056190DDL /* 532 */, 0xF5ADB0AEBB0F1491L /* 533 */,
+ 0x9B50F8850FD58892L /* 534 */, 0x4975488358B74DE8L /* 535 */,
+ 0xA3354FF691531C61L /* 536 */, 0x0702BBE481D2C6EEL /* 537 */,
+ 0x89FB24057DEDED98L /* 538 */, 0xAC3075138596E902L /* 539 */,
+ 0x1D2D3580172772EDL /* 540 */, 0xEB738FC28E6BC30DL /* 541 */,
+ 0x5854EF8F63044326L /* 542 */, 0x9E5C52325ADD3BBEL /* 543 */,
+ 0x90AA53CF325C4623L /* 544 */, 0xC1D24D51349DD067L /* 545 */,
+ 0x2051CFEEA69EA624L /* 546 */, 0x13220F0A862E7E4FL /* 547 */,
+ 0xCE39399404E04864L /* 548 */, 0xD9C42CA47086FCB7L /* 549 */,
+ 0x685AD2238A03E7CCL /* 550 */, 0x066484B2AB2FF1DBL /* 551 */,
+ 0xFE9D5D70EFBF79ECL /* 552 */, 0x5B13B9DD9C481854L /* 553 */,
+ 0x15F0D475ED1509ADL /* 554 */, 0x0BEBCD060EC79851L /* 555 */,
+ 0xD58C6791183AB7F8L /* 556 */, 0xD1187C5052F3EEE4L /* 557 */,
+ 0xC95D1192E54E82FFL /* 558 */, 0x86EEA14CB9AC6CA2L /* 559 */,
+ 0x3485BEB153677D5DL /* 560 */, 0xDD191D781F8C492AL /* 561 */,
+ 0xF60866BAA784EBF9L /* 562 */, 0x518F643BA2D08C74L /* 563 */,
+ 0x8852E956E1087C22L /* 564 */, 0xA768CB8DC410AE8DL /* 565 */,
+ 0x38047726BFEC8E1AL /* 566 */, 0xA67738B4CD3B45AAL /* 567 */,
+ 0xAD16691CEC0DDE19L /* 568 */, 0xC6D4319380462E07L /* 569 */,
+ 0xC5A5876D0BA61938L /* 570 */, 0x16B9FA1FA58FD840L /* 571 */,
+ 0x188AB1173CA74F18L /* 572 */, 0xABDA2F98C99C021FL /* 573 */,
+ 0x3E0580AB134AE816L /* 574 */, 0x5F3B05B773645ABBL /* 575 */,
+ 0x2501A2BE5575F2F6L /* 576 */, 0x1B2F74004E7E8BA9L /* 577 */,
+ 0x1CD7580371E8D953L /* 578 */, 0x7F6ED89562764E30L /* 579 */,
+ 0xB15926FF596F003DL /* 580 */, 0x9F65293DA8C5D6B9L /* 581 */,
+ 0x6ECEF04DD690F84CL /* 582 */, 0x4782275FFF33AF88L /* 583 */,
+ 0xE41433083F820801L /* 584 */, 0xFD0DFE409A1AF9B5L /* 585 */,
+ 0x4325A3342CDB396BL /* 586 */, 0x8AE77E62B301B252L /* 587 */,
+ 0xC36F9E9F6655615AL /* 588 */, 0x85455A2D92D32C09L /* 589 */,
+ 0xF2C7DEA949477485L /* 590 */, 0x63CFB4C133A39EBAL /* 591 */,
+ 0x83B040CC6EBC5462L /* 592 */, 0x3B9454C8FDB326B0L /* 593 */,
+ 0x56F56A9E87FFD78CL /* 594 */, 0x2DC2940D99F42BC6L /* 595 */,
+ 0x98F7DF096B096E2DL /* 596 */, 0x19A6E01E3AD852BFL /* 597 */,
+ 0x42A99CCBDBD4B40BL /* 598 */, 0xA59998AF45E9C559L /* 599 */,
+ 0x366295E807D93186L /* 600 */, 0x6B48181BFAA1F773L /* 601 */,
+ 0x1FEC57E2157A0A1DL /* 602 */, 0x4667446AF6201AD5L /* 603 */,
+ 0xE615EBCACFB0F075L /* 604 */, 0xB8F31F4F68290778L /* 605 */,
+ 0x22713ED6CE22D11EL /* 606 */, 0x3057C1A72EC3C93BL /* 607 */,
+ 0xCB46ACC37C3F1F2FL /* 608 */, 0xDBB893FD02AAF50EL /* 609 */,
+ 0x331FD92E600B9FCFL /* 610 */, 0xA498F96148EA3AD6L /* 611 */,
+ 0xA8D8426E8B6A83EAL /* 612 */, 0xA089B274B7735CDCL /* 613 */,
+ 0x87F6B3731E524A11L /* 614 */, 0x118808E5CBC96749L /* 615 */,
+ 0x9906E4C7B19BD394L /* 616 */, 0xAFED7F7E9B24A20CL /* 617 */,
+ 0x6509EADEEB3644A7L /* 618 */, 0x6C1EF1D3E8EF0EDEL /* 619 */,
+ 0xB9C97D43E9798FB4L /* 620 */, 0xA2F2D784740C28A3L /* 621 */,
+ 0x7B8496476197566FL /* 622 */, 0x7A5BE3E6B65F069DL /* 623 */,
+ 0xF96330ED78BE6F10L /* 624 */, 0xEEE60DE77A076A15L /* 625 */,
+ 0x2B4BEE4AA08B9BD0L /* 626 */, 0x6A56A63EC7B8894EL /* 627 */,
+ 0x02121359BA34FEF4L /* 628 */, 0x4CBF99F8283703FCL /* 629 */,
+ 0x398071350CAF30C8L /* 630 */, 0xD0A77A89F017687AL /* 631 */,
+ 0xF1C1A9EB9E423569L /* 632 */, 0x8C7976282DEE8199L /* 633 */,
+ 0x5D1737A5DD1F7ABDL /* 634 */, 0x4F53433C09A9FA80L /* 635 */,
+ 0xFA8B0C53DF7CA1D9L /* 636 */, 0x3FD9DCBC886CCB77L /* 637 */,
+ 0xC040917CA91B4720L /* 638 */, 0x7DD00142F9D1DCDFL /* 639 */,
+ 0x8476FC1D4F387B58L /* 640 */, 0x23F8E7C5F3316503L /* 641 */,
+ 0x032A2244E7E37339L /* 642 */, 0x5C87A5D750F5A74BL /* 643 */,
+ 0x082B4CC43698992EL /* 644 */, 0xDF917BECB858F63CL /* 645 */,
+ 0x3270B8FC5BF86DDAL /* 646 */, 0x10AE72BB29B5DD76L /* 647 */,
+ 0x576AC94E7700362BL /* 648 */, 0x1AD112DAC61EFB8FL /* 649 */,
+ 0x691BC30EC5FAA427L /* 650 */, 0xFF246311CC327143L /* 651 */,
+ 0x3142368E30E53206L /* 652 */, 0x71380E31E02CA396L /* 653 */,
+ 0x958D5C960AAD76F1L /* 654 */, 0xF8D6F430C16DA536L /* 655 */,
+ 0xC8FFD13F1BE7E1D2L /* 656 */, 0x7578AE66004DDBE1L /* 657 */,
+ 0x05833F01067BE646L /* 658 */, 0xBB34B5AD3BFE586DL /* 659 */,
+ 0x095F34C9A12B97F0L /* 660 */, 0x247AB64525D60CA8L /* 661 */,
+ 0xDCDBC6F3017477D1L /* 662 */, 0x4A2E14D4DECAD24DL /* 663 */,
+ 0xBDB5E6D9BE0A1EEBL /* 664 */, 0x2A7E70F7794301ABL /* 665 */,
+ 0xDEF42D8A270540FDL /* 666 */, 0x01078EC0A34C22C1L /* 667 */,
+ 0xE5DE511AF4C16387L /* 668 */, 0x7EBB3A52BD9A330AL /* 669 */,
+ 0x77697857AA7D6435L /* 670 */, 0x004E831603AE4C32L /* 671 */,
+ 0xE7A21020AD78E312L /* 672 */, 0x9D41A70C6AB420F2L /* 673 */,
+ 0x28E06C18EA1141E6L /* 674 */, 0xD2B28CBD984F6B28L /* 675 */,
+ 0x26B75F6C446E9D83L /* 676 */, 0xBA47568C4D418D7FL /* 677 */,
+ 0xD80BADBFE6183D8EL /* 678 */, 0x0E206D7F5F166044L /* 679 */,
+ 0xE258A43911CBCA3EL /* 680 */, 0x723A1746B21DC0BCL /* 681 */,
+ 0xC7CAA854F5D7CDD3L /* 682 */, 0x7CAC32883D261D9CL /* 683 */,
+ 0x7690C26423BA942CL /* 684 */, 0x17E55524478042B8L /* 685 */,
+ 0xE0BE477656A2389FL /* 686 */, 0x4D289B5E67AB2DA0L /* 687 */,
+ 0x44862B9C8FBBFD31L /* 688 */, 0xB47CC8049D141365L /* 689 */,
+ 0x822C1B362B91C793L /* 690 */, 0x4EB14655FB13DFD8L /* 691 */,
+ 0x1ECBBA0714E2A97BL /* 692 */, 0x6143459D5CDE5F14L /* 693 */,
+ 0x53A8FBF1D5F0AC89L /* 694 */, 0x97EA04D81C5E5B00L /* 695 */,
+ 0x622181A8D4FDB3F3L /* 696 */, 0xE9BCD341572A1208L /* 697 */,
+ 0x1411258643CCE58AL /* 698 */, 0x9144C5FEA4C6E0A4L /* 699 */,
+ 0x0D33D06565CF620FL /* 700 */, 0x54A48D489F219CA1L /* 701 */,
+ 0xC43E5EAC6D63C821L /* 702 */, 0xA9728B3A72770DAFL /* 703 */,
+ 0xD7934E7B20DF87EFL /* 704 */, 0xE35503B61A3E86E5L /* 705 */,
+ 0xCAE321FBC819D504L /* 706 */, 0x129A50B3AC60BFA6L /* 707 */,
+ 0xCD5E68EA7E9FB6C3L /* 708 */, 0xB01C90199483B1C7L /* 709 */,
+ 0x3DE93CD5C295376CL /* 710 */, 0xAED52EDF2AB9AD13L /* 711 */,
+ 0x2E60F512C0A07884L /* 712 */, 0xBC3D86A3E36210C9L /* 713 */,
+ 0x35269D9B163951CEL /* 714 */, 0x0C7D6E2AD0CDB5FAL /* 715 */,
+ 0x59E86297D87F5733L /* 716 */, 0x298EF221898DB0E7L /* 717 */,
+ 0x55000029D1A5AA7EL /* 718 */, 0x8BC08AE1B5061B45L /* 719 */,
+ 0xC2C31C2B6C92703AL /* 720 */, 0x94CC596BAF25EF42L /* 721 */,
+ 0x0A1D73DB22540456L /* 722 */, 0x04B6A0F9D9C4179AL /* 723 */,
+ 0xEFFDAFA2AE3D3C60L /* 724 */, 0xF7C8075BB49496C4L /* 725 */,
+ 0x9CC5C7141D1CD4E3L /* 726 */, 0x78BD1638218E5534L /* 727 */,
+ 0xB2F11568F850246AL /* 728 */, 0xEDFABCFA9502BC29L /* 729 */,
+ 0x796CE5F2DA23051BL /* 730 */, 0xAAE128B0DC93537CL /* 731 */,
+ 0x3A493DA0EE4B29AEL /* 732 */, 0xB5DF6B2C416895D7L /* 733 */,
+ 0xFCABBD25122D7F37L /* 734 */, 0x70810B58105DC4B1L /* 735 */,
+ 0xE10FDD37F7882A90L /* 736 */, 0x524DCAB5518A3F5CL /* 737 */,
+ 0x3C9E85878451255BL /* 738 */, 0x4029828119BD34E2L /* 739 */,
+ 0x74A05B6F5D3CECCBL /* 740 */, 0xB610021542E13ECAL /* 741 */,
+ 0x0FF979D12F59E2ACL /* 742 */, 0x6037DA27E4F9CC50L /* 743 */,
+ 0x5E92975A0DF1847DL /* 744 */, 0xD66DE190D3E623FEL /* 745 */,
+ 0x5032D6B87B568048L /* 746 */, 0x9A36B7CE8235216EL /* 747 */,
+ 0x80272A7A24F64B4AL /* 748 */, 0x93EFED8B8C6916F7L /* 749 */,
+ 0x37DDBFF44CCE1555L /* 750 */, 0x4B95DB5D4B99BD25L /* 751 */,
+ 0x92D3FDA169812FC0L /* 752 */, 0xFB1A4A9A90660BB6L /* 753 */,
+ 0x730C196946A4B9B2L /* 754 */, 0x81E289AA7F49DA68L /* 755 */,
+ 0x64669A0F83B1A05FL /* 756 */, 0x27B3FF7D9644F48BL /* 757 */,
+ 0xCC6B615C8DB675B3L /* 758 */, 0x674F20B9BCEBBE95L /* 759 */,
+ 0x6F31238275655982L /* 760 */, 0x5AE488713E45CF05L /* 761 */,
+ 0xBF619F9954C21157L /* 762 */, 0xEABAC46040A8EAE9L /* 763 */,
+ 0x454C6FE9F2C0C1CDL /* 764 */, 0x419CF6496412691CL /* 765 */,
+ 0xD3DC3BEF265B0F70L /* 766 */, 0x6D0E60F5C3578A9EL /* 767 */,
+ };
+
+ private static final long[] t4 = {
+ 0x5B0E608526323C55L /* 768 */, 0x1A46C1A9FA1B59F5L /* 769 */,
+ 0xA9E245A17C4C8FFAL /* 770 */, 0x65CA5159DB2955D7L /* 771 */,
+ 0x05DB0A76CE35AFC2L /* 772 */, 0x81EAC77EA9113D45L /* 773 */,
+ 0x528EF88AB6AC0A0DL /* 774 */, 0xA09EA253597BE3FFL /* 775 */,
+ 0x430DDFB3AC48CD56L /* 776 */, 0xC4B3A67AF45CE46FL /* 777 */,
+ 0x4ECECFD8FBE2D05EL /* 778 */, 0x3EF56F10B39935F0L /* 779 */,
+ 0x0B22D6829CD619C6L /* 780 */, 0x17FD460A74DF2069L /* 781 */,
+ 0x6CF8CC8E8510ED40L /* 782 */, 0xD6C824BF3A6ECAA7L /* 783 */,
+ 0x61243D581A817049L /* 784 */, 0x048BACB6BBC163A2L /* 785 */,
+ 0xD9A38AC27D44CC32L /* 786 */, 0x7FDDFF5BAAF410ABL /* 787 */,
+ 0xAD6D495AA804824BL /* 788 */, 0xE1A6A74F2D8C9F94L /* 789 */,
+ 0xD4F7851235DEE8E3L /* 790 */, 0xFD4B7F886540D893L /* 791 */,
+ 0x247C20042AA4BFDAL /* 792 */, 0x096EA1C517D1327CL /* 793 */,
+ 0xD56966B4361A6685L /* 794 */, 0x277DA5C31221057DL /* 795 */,
+ 0x94D59893A43ACFF7L /* 796 */, 0x64F0C51CCDC02281L /* 797 */,
+ 0x3D33BCC4FF6189DBL /* 798 */, 0xE005CB184CE66AF1L /* 799 */,
+ 0xFF5CCD1D1DB99BEAL /* 800 */, 0xB0B854A7FE42980FL /* 801 */,
+ 0x7BD46A6A718D4B9FL /* 802 */, 0xD10FA8CC22A5FD8CL /* 803 */,
+ 0xD31484952BE4BD31L /* 804 */, 0xC7FA975FCB243847L /* 805 */,
+ 0x4886ED1E5846C407L /* 806 */, 0x28CDDB791EB70B04L /* 807 */,
+ 0xC2B00BE2F573417FL /* 808 */, 0x5C9590452180F877L /* 809 */,
+ 0x7A6BDDFFF370EB00L /* 810 */, 0xCE509E38D6D9D6A4L /* 811 */,
+ 0xEBEB0F00647FA702L /* 812 */, 0x1DCC06CF76606F06L /* 813 */,
+ 0xE4D9F28BA286FF0AL /* 814 */, 0xD85A305DC918C262L /* 815 */,
+ 0x475B1D8732225F54L /* 816 */, 0x2D4FB51668CCB5FEL /* 817 */,
+ 0xA679B9D9D72BBA20L /* 818 */, 0x53841C0D912D43A5L /* 819 */,
+ 0x3B7EAA48BF12A4E8L /* 820 */, 0x781E0E47F22F1DDFL /* 821 */,
+ 0xEFF20CE60AB50973L /* 822 */, 0x20D261D19DFFB742L /* 823 */,
+ 0x16A12B03062A2E39L /* 824 */, 0x1960EB2239650495L /* 825 */,
+ 0x251C16FED50EB8B8L /* 826 */, 0x9AC0C330F826016EL /* 827 */,
+ 0xED152665953E7671L /* 828 */, 0x02D63194A6369570L /* 829 */,
+ 0x5074F08394B1C987L /* 830 */, 0x70BA598C90B25CE1L /* 831 */,
+ 0x794A15810B9742F6L /* 832 */, 0x0D5925E9FCAF8C6CL /* 833 */,
+ 0x3067716CD868744EL /* 834 */, 0x910AB077E8D7731BL /* 835 */,
+ 0x6A61BBDB5AC42F61L /* 836 */, 0x93513EFBF0851567L /* 837 */,
+ 0xF494724B9E83E9D5L /* 838 */, 0xE887E1985C09648DL /* 839 */,
+ 0x34B1D3C675370CFDL /* 840 */, 0xDC35E433BC0D255DL /* 841 */,
+ 0xD0AAB84234131BE0L /* 842 */, 0x08042A50B48B7EAFL /* 843 */,
+ 0x9997C4EE44A3AB35L /* 844 */, 0x829A7B49201799D0L /* 845 */,
+ 0x263B8307B7C54441L /* 846 */, 0x752F95F4FD6A6CA6L /* 847 */,
+ 0x927217402C08C6E5L /* 848 */, 0x2A8AB754A795D9EEL /* 849 */,
+ 0xA442F7552F72943DL /* 850 */, 0x2C31334E19781208L /* 851 */,
+ 0x4FA98D7CEAEE6291L /* 852 */, 0x55C3862F665DB309L /* 853 */,
+ 0xBD0610175D53B1F3L /* 854 */, 0x46FE6CB840413F27L /* 855 */,
+ 0x3FE03792DF0CFA59L /* 856 */, 0xCFE700372EB85E8FL /* 857 */,
+ 0xA7BE29E7ADBCE118L /* 858 */, 0xE544EE5CDE8431DDL /* 859 */,
+ 0x8A781B1B41F1873EL /* 860 */, 0xA5C94C78A0D2F0E7L /* 861 */,
+ 0x39412E2877B60728L /* 862 */, 0xA1265EF3AFC9A62CL /* 863 */,
+ 0xBCC2770C6A2506C5L /* 864 */, 0x3AB66DD5DCE1CE12L /* 865 */,
+ 0xE65499D04A675B37L /* 866 */, 0x7D8F523481BFD216L /* 867 */,
+ 0x0F6F64FCEC15F389L /* 868 */, 0x74EFBE618B5B13C8L /* 869 */,
+ 0xACDC82B714273E1DL /* 870 */, 0xDD40BFE003199D17L /* 871 */,
+ 0x37E99257E7E061F8L /* 872 */, 0xFA52626904775AAAL /* 873 */,
+ 0x8BBBF63A463D56F9L /* 874 */, 0xF0013F1543A26E64L /* 875 */,
+ 0xA8307E9F879EC898L /* 876 */, 0xCC4C27A4150177CCL /* 877 */,
+ 0x1B432F2CCA1D3348L /* 878 */, 0xDE1D1F8F9F6FA013L /* 879 */,
+ 0x606602A047A7DDD6L /* 880 */, 0xD237AB64CC1CB2C7L /* 881 */,
+ 0x9B938E7225FCD1D3L /* 882 */, 0xEC4E03708E0FF476L /* 883 */,
+ 0xFEB2FBDA3D03C12DL /* 884 */, 0xAE0BCED2EE43889AL /* 885 */,
+ 0x22CB8923EBFB4F43L /* 886 */, 0x69360D013CF7396DL /* 887 */,
+ 0x855E3602D2D4E022L /* 888 */, 0x073805BAD01F784CL /* 889 */,
+ 0x33E17A133852F546L /* 890 */, 0xDF4874058AC7B638L /* 891 */,
+ 0xBA92B29C678AA14AL /* 892 */, 0x0CE89FC76CFAADCDL /* 893 */,
+ 0x5F9D4E0908339E34L /* 894 */, 0xF1AFE9291F5923B9L /* 895 */,
+ 0x6E3480F60F4A265FL /* 896 */, 0xEEBF3A2AB29B841CL /* 897 */,
+ 0xE21938A88F91B4ADL /* 898 */, 0x57DFEFF845C6D3C3L /* 899 */,
+ 0x2F006B0BF62CAAF2L /* 900 */, 0x62F479EF6F75EE78L /* 901 */,
+ 0x11A55AD41C8916A9L /* 902 */, 0xF229D29084FED453L /* 903 */,
+ 0x42F1C27B16B000E6L /* 904 */, 0x2B1F76749823C074L /* 905 */,
+ 0x4B76ECA3C2745360L /* 906 */, 0x8C98F463B91691BDL /* 907 */,
+ 0x14BCC93CF1ADE66AL /* 908 */, 0x8885213E6D458397L /* 909 */,
+ 0x8E177DF0274D4711L /* 910 */, 0xB49B73B5503F2951L /* 911 */,
+ 0x10168168C3F96B6BL /* 912 */, 0x0E3D963B63CAB0AEL /* 913 */,
+ 0x8DFC4B5655A1DB14L /* 914 */, 0xF789F1356E14DE5CL /* 915 */,
+ 0x683E68AF4E51DAC1L /* 916 */, 0xC9A84F9D8D4B0FD9L /* 917 */,
+ 0x3691E03F52A0F9D1L /* 918 */, 0x5ED86E46E1878E80L /* 919 */,
+ 0x3C711A0E99D07150L /* 920 */, 0x5A0865B20C4E9310L /* 921 */,
+ 0x56FBFC1FE4F0682EL /* 922 */, 0xEA8D5DE3105EDF9BL /* 923 */,
+ 0x71ABFDB12379187AL /* 924 */, 0x2EB99DE1BEE77B9CL /* 925 */,
+ 0x21ECC0EA33CF4523L /* 926 */, 0x59A4D7521805C7A1L /* 927 */,
+ 0x3896F5EB56AE7C72L /* 928 */, 0xAA638F3DB18F75DCL /* 929 */,
+ 0x9F39358DABE9808EL /* 930 */, 0xB7DEFA91C00B72ACL /* 931 */,
+ 0x6B5541FD62492D92L /* 932 */, 0x6DC6DEE8F92E4D5BL /* 933 */,
+ 0x353F57ABC4BEEA7EL /* 934 */, 0x735769D6DA5690CEL /* 935 */,
+ 0x0A234AA642391484L /* 936 */, 0xF6F9508028F80D9DL /* 937 */,
+ 0xB8E319A27AB3F215L /* 938 */, 0x31AD9C1151341A4DL /* 939 */,
+ 0x773C22A57BEF5805L /* 940 */, 0x45C7561A07968633L /* 941 */,
+ 0xF913DA9E249DBE36L /* 942 */, 0xDA652D9B78A64C68L /* 943 */,
+ 0x4C27A97F3BC334EFL /* 944 */, 0x76621220E66B17F4L /* 945 */,
+ 0x967743899ACD7D0BL /* 946 */, 0xF3EE5BCAE0ED6782L /* 947 */,
+ 0x409F753600C879FCL /* 948 */, 0x06D09A39B5926DB6L /* 949 */,
+ 0x6F83AEB0317AC588L /* 950 */, 0x01E6CA4A86381F21L /* 951 */,
+ 0x66FF3462D19F3025L /* 952 */, 0x72207C24DDFD3BFBL /* 953 */,
+ 0x4AF6B6D3E2ECE2EBL /* 954 */, 0x9C994DBEC7EA08DEL /* 955 */,
+ 0x49ACE597B09A8BC4L /* 956 */, 0xB38C4766CF0797BAL /* 957 */,
+ 0x131B9373C57C2A75L /* 958 */, 0xB1822CCE61931E58L /* 959 */,
+ 0x9D7555B909BA1C0CL /* 960 */, 0x127FAFDD937D11D2L /* 961 */,
+ 0x29DA3BADC66D92E4L /* 962 */, 0xA2C1D57154C2ECBCL /* 963 */,
+ 0x58C5134D82F6FE24L /* 964 */, 0x1C3AE3515B62274FL /* 965 */,
+ 0xE907C82E01CB8126L /* 966 */, 0xF8ED091913E37FCBL /* 967 */,
+ 0x3249D8F9C80046C9L /* 968 */, 0x80CF9BEDE388FB63L /* 969 */,
+ 0x1881539A116CF19EL /* 970 */, 0x5103F3F76BD52457L /* 971 */,
+ 0x15B7E6F5AE47F7A8L /* 972 */, 0xDBD7C6DED47E9CCFL /* 973 */,
+ 0x44E55C410228BB1AL /* 974 */, 0xB647D4255EDB4E99L /* 975 */,
+ 0x5D11882BB8AAFC30L /* 976 */, 0xF5098BBB29D3212AL /* 977 */,
+ 0x8FB5EA14E90296B3L /* 978 */, 0x677B942157DD025AL /* 979 */,
+ 0xFB58E7C0A390ACB5L /* 980 */, 0x89D3674C83BD4A01L /* 981 */,
+ 0x9E2DA4DF4BF3B93BL /* 982 */, 0xFCC41E328CAB4829L /* 983 */,
+ 0x03F38C96BA582C52L /* 984 */, 0xCAD1BDBD7FD85DB2L /* 985 */,
+ 0xBBB442C16082AE83L /* 986 */, 0xB95FE86BA5DA9AB0L /* 987 */,
+ 0xB22E04673771A93FL /* 988 */, 0x845358C9493152D8L /* 989 */,
+ 0xBE2A488697B4541EL /* 990 */, 0x95A2DC2DD38E6966L /* 991 */,
+ 0xC02C11AC923C852BL /* 992 */, 0x2388B1990DF2A87BL /* 993 */,
+ 0x7C8008FA1B4F37BEL /* 994 */, 0x1F70D0C84D54E503L /* 995 */,
+ 0x5490ADEC7ECE57D4L /* 996 */, 0x002B3C27D9063A3AL /* 997 */,
+ 0x7EAEA3848030A2BFL /* 998 */, 0xC602326DED2003C0L /* 999 */,
+ 0x83A7287D69A94086L /* 1000 */, 0xC57A5FCB30F57A8AL /* 1001 */,
+ 0xB56844E479EBE779L /* 1002 */, 0xA373B40F05DCBCE9L /* 1003 */,
+ 0xD71A786E88570EE2L /* 1004 */, 0x879CBACDBDE8F6A0L /* 1005 */,
+ 0x976AD1BCC164A32FL /* 1006 */, 0xAB21E25E9666D78BL /* 1007 */,
+ 0x901063AAE5E5C33CL /* 1008 */, 0x9818B34448698D90L /* 1009 */,
+ 0xE36487AE3E1E8ABBL /* 1010 */, 0xAFBDF931893BDCB4L /* 1011 */,
+ 0x6345A0DC5FBBD519L /* 1012 */, 0x8628FE269B9465CAL /* 1013 */,
+ 0x1E5D01603F9C51ECL /* 1014 */, 0x4DE44006A15049B7L /* 1015 */,
+ 0xBF6C70E5F776CBB1L /* 1016 */, 0x411218F2EF552BEDL /* 1017 */,
+ 0xCB0C0708705A36A3L /* 1018 */, 0xE74D14754F986044L /* 1019 */,
+ 0xCD56D9430EA8280EL /* 1020 */, 0xC12591D7535F5065L /* 1021 */,
+ 0xC83223F1720AEF96L /* 1022 */, 0xC3A0396F7363A51FL /* 1023 */
+ };
+
+ private static final int DIGEST_LENGTH = 24;
+
+ //
+ // registers
+ //
+ private long a, b, c;
+ private long byteCount;
+
+ //
+ // buffers
+ //
+ private byte[] buf = new byte[8];
+ private int bOff = 0;
+
+ private long[] x = new long[8];
+ private int xOff = 0;
+
+ /**
+ * Standard constructor
+ */
+ public TigerDigest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public TigerDigest(TigerDigest t)
+ {
+ a = t.a;
+ b = t.b;
+ c = t.c;
+
+ System.arraycopy(t.x, 0, x, 0, t.x.length);
+ xOff = t.xOff;
+
+ System.arraycopy(t.buf, 0, buf, 0, t.buf.length);
+ bOff = t.bOff;
+
+ byteCount = t.byteCount;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Tiger";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ private void processWord(
+ byte[] b,
+ int off)
+ {
+ x[xOff++] = ((long)(b[off + 7] & 0xff) << 56)
+ | ((long)(b[off + 6] & 0xff) << 48)
+ | ((long)(b[off + 5] & 0xff) << 40)
+ | ((long)(b[off + 4] & 0xff) << 32)
+ | ((long)(b[off + 3] & 0xff) << 24)
+ | ((long)(b[off + 2] & 0xff) << 16)
+ | ((long)(b[off + 1] & 0xff) << 8)
+ | ((b[off + 0] & 0xff));
+
+ if (xOff == x.length)
+ {
+ processBlock();
+ }
+
+ bOff = 0;
+ }
+
+ public void update(
+ byte in)
+ {
+ buf[bOff++] = in;
+
+ if (bOff == buf.length)
+ {
+ processWord(buf, 0);
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((bOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > 8)
+ {
+ processWord(in, inOff);
+
+ inOff += 8;
+ len -= 8;
+ byteCount += 8;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ private void roundABC(
+ long x,
+ long mul)
+ {
+ c ^= x ;
+ a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
+ ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
+ b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
+ ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
+ b *= mul;
+ }
+
+ private void roundBCA(
+ long x,
+ long mul)
+ {
+ a ^= x ;
+ b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
+ ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
+ c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
+ ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
+ c *= mul;
+ }
+
+ private void roundCAB(
+ long x,
+ long mul)
+ {
+ b ^= x ;
+ c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
+ ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
+ a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
+ ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
+ a *= mul;
+ }
+
+ private void keySchedule()
+ {
+ x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L;
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1]) << 19);
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4]) >>> 23);
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7]) << 19);
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2]) >>> 23);
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ 0x0123456789ABCDEFL;
+ }
+
+ private void processBlock()
+ {
+ //
+ // save abc
+ //
+ long aa = a;
+ long bb = b;
+ long cc = c;
+
+ //
+ // rounds and schedule
+ //
+ roundABC(x[0], 5);
+ roundBCA(x[1], 5);
+ roundCAB(x[2], 5);
+ roundABC(x[3], 5);
+ roundBCA(x[4], 5);
+ roundCAB(x[5], 5);
+ roundABC(x[6], 5);
+ roundBCA(x[7], 5);
+
+ keySchedule();
+
+ roundCAB(x[0], 7);
+ roundABC(x[1], 7);
+ roundBCA(x[2], 7);
+ roundCAB(x[3], 7);
+ roundABC(x[4], 7);
+ roundBCA(x[5], 7);
+ roundCAB(x[6], 7);
+ roundABC(x[7], 7);
+
+ keySchedule();
+
+ roundBCA(x[0], 9);
+ roundCAB(x[1], 9);
+ roundABC(x[2], 9);
+ roundBCA(x[3], 9);
+ roundCAB(x[4], 9);
+ roundABC(x[5], 9);
+ roundBCA(x[6], 9);
+ roundCAB(x[7], 9);
+
+ //
+ // feed forward
+ //
+ a ^= aa;
+ b -= bb;
+ c += cc;
+
+ //
+ // clear the x buffer
+ //
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+ }
+
+ public void unpackWord(
+ long r,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 7] = (byte)(r >> 56);
+ out[outOff + 6] = (byte)(r >> 48);
+ out[outOff + 5] = (byte)(r >> 40);
+ out[outOff + 4] = (byte)(r >> 32);
+ out[outOff + 3] = (byte)(r >> 24);
+ out[outOff + 2] = (byte)(r >> 16);
+ out[outOff + 1] = (byte)(r >> 8);
+ out[outOff] = (byte)r;
+ }
+
+ private void processLength(
+ long bitLength)
+ {
+ x[7] = bitLength;
+ }
+
+ private void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ update((byte)0x01);
+
+ while (bOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(a, out, outOff);
+ unpackWord(b, out, outOff + 8);
+ unpackWord(c, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ a = 0x0123456789ABCDEFL;
+ b = 0xFEDCBA9876543210L;
+ c = 0xF096A5B4C3B2E187L;
+
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+
+ bOff = 0;
+ for (int i = 0; i != buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ byteCount = 0;
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/Salsa20Engine.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/Salsa20Engine.java
new file mode 100644
index 00000000..c51d120b
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/Salsa20Engine.java
@@ -0,0 +1,377 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.MaxBytesExceededException;
+import org.bouncycastle.crypto.StreamCipher;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+ */
+
+public class Salsa20Engine
+ implements StreamCipher
+{
+ /** Constants */
+ private final static int stateSize = 16; // 16, 32 bit ints = 64 bytes
+
+ private final static byte[]
+ sigma = toByteArray("expand 32-byte k"),
+ tau = toByteArray("expand 16-byte k");
+
+ // No sure why the version in org.bouncycastle.util.Strings was throwing NoSuchMethodErrors
+ private static byte[] toByteArray(String string)
+ {
+ byte[] bytes = new byte[string.length()];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ char ch = string.charAt(i);
+
+ bytes[i] = (byte)ch;
+ }
+
+ return bytes;
+ }
+
+
+ /*
+ * variables to hold the state of the engine
+ * during encryption and decryption
+ */
+ private int index = 0;
+ private int[] engineState = new int[stateSize]; // state
+ private int[] x = new int[stateSize] ; // internal buffer
+ private byte[] keyStream = new byte[stateSize * 4], // expanded state, 64 bytes
+ workingKey = null,
+ workingIV = null;
+ private boolean initialised = false;
+
+ /*
+ * internal counter
+ */
+ private int cW0, cW1, cW2;
+
+
+ /**
+ * initialise a Salsa20 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ /*
+ * Salsa20 encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant. (Like 90% of stream ciphers)
+ */
+
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException("Salsa20 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 8)
+ {
+ throw new IllegalArgumentException("Salsa20 requires exactly 8 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("Salsa20 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
+ workingKey = key.getKey();
+ workingIV = iv;
+
+ setKey(workingKey, workingIV);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Salsa20";
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (limitExceeded())
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
+ }
+
+ if (index == 0)
+ {
+ salsa20WordToByte(engineState, keyStream);
+ engineState[8]++;
+ if (engineState[8] == 0)
+ {
+ engineState[9]++;
+ }
+ }
+ byte out = (byte)(keyStream[index]^in);
+ index = (index + 1) & 63;
+
+ return out;
+ }
+
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (limitExceeded(len))
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (index == 0)
+ {
+ salsa20WordToByte(engineState, keyStream);
+ engineState[8]++;
+ if (engineState[8] == 0)
+ {
+ engineState[9]++;
+ }
+ }
+ out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
+ index = (index + 1) & 63;
+ }
+ }
+
+ public void reset()
+ {
+ setKey(workingKey, workingIV);
+ }
+
+ // Private implementation
+
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ index = 0;
+ resetCounter();
+ int offset = 0;
+ byte[] constants;
+
+ // Key
+ engineState[1] = byteToIntLittle(workingKey, 0);
+ engineState[2] = byteToIntLittle(workingKey, 4);
+ engineState[3] = byteToIntLittle(workingKey, 8);
+ engineState[4] = byteToIntLittle(workingKey, 12);
+
+ if (workingKey.length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ }
+ else
+ {
+ constants = tau;
+ }
+
+ engineState[11] = byteToIntLittle(workingKey, offset);
+ engineState[12] = byteToIntLittle(workingKey, offset+4);
+ engineState[13] = byteToIntLittle(workingKey, offset+8);
+ engineState[14] = byteToIntLittle(workingKey, offset+12);
+ engineState[0 ] = byteToIntLittle(constants, 0);
+ engineState[5 ] = byteToIntLittle(constants, 4);
+ engineState[10] = byteToIntLittle(constants, 8);
+ engineState[15] = byteToIntLittle(constants, 12);
+
+ // IV
+ engineState[6] = byteToIntLittle(workingIV, 0);
+ engineState[7] = byteToIntLittle(workingIV, 4);
+ engineState[8] = engineState[9] = 0;
+
+ initialised = true;
+ }
+
+ /**
+ * Salsa20 function
+ *
+ * @param input input data
+ *
+ * @return keystream
+ */
+ private void salsa20WordToByte(int[] input, byte[] output)
+ {
+ System.arraycopy(input, 0, x, 0, input.length);
+
+ for (int i = 0; i < 10; i++)
+ {
+ x[ 4] ^= rotl((x[ 0]+x[12]), 7);
+ x[ 8] ^= rotl((x[ 4]+x[ 0]), 9);
+ x[12] ^= rotl((x[ 8]+x[ 4]),13);
+ x[ 0] ^= rotl((x[12]+x[ 8]),18);
+ x[ 9] ^= rotl((x[ 5]+x[ 1]), 7);
+ x[13] ^= rotl((x[ 9]+x[ 5]), 9);
+ x[ 1] ^= rotl((x[13]+x[ 9]),13);
+ x[ 5] ^= rotl((x[ 1]+x[13]),18);
+ x[14] ^= rotl((x[10]+x[ 6]), 7);
+ x[ 2] ^= rotl((x[14]+x[10]), 9);
+ x[ 6] ^= rotl((x[ 2]+x[14]),13);
+ x[10] ^= rotl((x[ 6]+x[ 2]),18);
+ x[ 3] ^= rotl((x[15]+x[11]), 7);
+ x[ 7] ^= rotl((x[ 3]+x[15]), 9);
+ x[11] ^= rotl((x[ 7]+x[ 3]),13);
+ x[15] ^= rotl((x[11]+x[ 7]),18);
+ x[ 1] ^= rotl((x[ 0]+x[ 3]), 7);
+ x[ 2] ^= rotl((x[ 1]+x[ 0]), 9);
+ x[ 3] ^= rotl((x[ 2]+x[ 1]),13);
+ x[ 0] ^= rotl((x[ 3]+x[ 2]),18);
+ x[ 6] ^= rotl((x[ 5]+x[ 4]), 7);
+ x[ 7] ^= rotl((x[ 6]+x[ 5]), 9);
+ x[ 4] ^= rotl((x[ 7]+x[ 6]),13);
+ x[ 5] ^= rotl((x[ 4]+x[ 7]),18);
+ x[11] ^= rotl((x[10]+x[ 9]), 7);
+ x[ 8] ^= rotl((x[11]+x[10]), 9);
+ x[ 9] ^= rotl((x[ 8]+x[11]),13);
+ x[10] ^= rotl((x[ 9]+x[ 8]),18);
+ x[12] ^= rotl((x[15]+x[14]), 7);
+ x[13] ^= rotl((x[12]+x[15]), 9);
+ x[14] ^= rotl((x[13]+x[12]),13);
+ x[15] ^= rotl((x[14]+x[13]),18);
+ }
+
+ int offset = 0;
+ for (int i = 0; i < stateSize; i++)
+ {
+ intToByteLittle(x[i] + input[i], output, offset);
+ offset += 4;
+ }
+
+ for (int i = stateSize; i < x.length; i++)
+ {
+ intToByteLittle(x[i], output, offset);
+ offset += 4;
+ }
+ }
+
+ /**
+ * 32 bit word to 4 byte array in little endian order
+ *
+ * @param x value to 'unpack'
+ *
+ * @return value of x expressed as a byte[] array in little endian order
+ */
+ private byte[] intToByteLittle(int x, byte[] out, int off)
+ {
+ out[off] = (byte)x;
+ out[off + 1] = (byte)(x >>> 8);
+ out[off + 2] = (byte)(x >>> 16);
+ out[off + 3] = (byte)(x >>> 24);
+ return out;
+ }
+
+ /**
+ * Rotate left
+ *
+ * @param x value to rotate
+ * @param y amount to rotate x
+ *
+ * @return rotated x
+ */
+ private int rotl(int x, int y)
+ {
+ return (x << y) | (x >>> -y);
+ }
+
+ /**
+ * Pack byte[] array into an int in little endian order
+ *
+ * @param x byte array to 'pack'
+ * @param offset only x[offset]..x[offset+3] will be packed
+ *
+ * @return x[offset]..x[offset+3] 'packed' into an int in little-endian order
+ */
+ private int byteToIntLittle(byte[] x, int offset)
+ {
+ return ((x[offset] & 255)) |
+ ((x[offset + 1] & 255) << 8) |
+ ((x[offset + 2] & 255) << 16) |
+ (x[offset + 3] << 24);
+ }
+
+ private void resetCounter()
+ {
+ cW0 = 0;
+ cW1 = 0;
+ cW2 = 0;
+ }
+
+ private boolean limitExceeded()
+ {
+ cW0++;
+ if (cW0 == 0)
+ {
+ cW1++;
+ if (cW1 == 0)
+ {
+ cW2++;
+ return (cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+
+ return false;
+ }
+
+ /*
+ * this relies on the fact len will always be positive.
+ */
+ private boolean limitExceeded(int len)
+ {
+ if (cW0 >= 0)
+ {
+ cW0 += len;
+ }
+ else
+ {
+ cW0 += len;
+ if (cW0 >= 0)
+ {
+ cW1++;
+ if (cW1 == 0)
+ {
+ cW2++;
+ return (cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/TwofishEngine.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/TwofishEngine.java
new file mode 100644
index 00000000..adb908eb
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/engines/TwofishEngine.java
@@ -0,0 +1,677 @@
+package org.bouncycastle.crypto.engines;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides Twofish encryption operations.
+ *
+ * This Java implementation is based on the Java reference
+ * implementation provided by Bruce Schneier and developed
+ * by Raif S. Naffah.
+ */
+public final class TwofishEngine
+ implements BlockCipher
+{
+ private static final byte[][] P = {
+ { // p0
+ (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+ (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+ (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+ (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+ (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+ (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+ (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+ (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+ (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+ (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+ (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+ (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+ (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+ (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+ (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+ (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+ (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+ (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+ (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+ (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+ (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+ (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+ (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+ (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+ (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+ (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+ (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+ (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+ (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+ (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+ (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+ (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+ (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+ (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+ (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+ (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+ (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+ (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+ (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+ (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+ (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+ (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+ (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+ (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+ (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+ (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+ (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+ (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+ (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+ (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+ (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+ (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+ (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+ (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+ (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+ (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+ (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+ (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+ (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+ (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+ (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+ (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+ (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+ (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
+ { // p1
+ (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+ (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+ (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+ (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+ (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+ (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+ (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+ (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+ (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+ (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+ (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+ (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+ (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+ (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+ (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+ (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+ (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+ (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+ (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+ (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+ (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+ (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+ (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+ (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+ (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+ (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+ (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+ (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+ (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+ (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+ (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+ (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+ (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+ (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+ (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+ (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+ (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+ (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+ (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+ (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+ (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+ (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+ (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+ (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+ (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+ (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+ (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+ (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+ (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+ (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+ (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+ (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+ (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+ (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+ (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+ (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+ (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+ (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+ (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+ (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+ (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+ (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+ (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+ (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 }
+ };
+
+ /**
+ * Define the fixed p0/p1 permutations used in keyed S-box lookup.
+ * By changing the following constant definitions, the S-boxes will
+ * automatically get changed in the Twofish engine.
+ */
+ private static final int P_00 = 1;
+ private static final int P_01 = 0;
+ private static final int P_02 = 0;
+ private static final int P_03 = P_01 ^ 1;
+ private static final int P_04 = 1;
+
+ private static final int P_10 = 0;
+ private static final int P_11 = 0;
+ private static final int P_12 = 1;
+ private static final int P_13 = P_11 ^ 1;
+ private static final int P_14 = 0;
+
+ private static final int P_20 = 1;
+ private static final int P_21 = 1;
+ private static final int P_22 = 0;
+ private static final int P_23 = P_21 ^ 1;
+ private static final int P_24 = 0;
+
+ private static final int P_30 = 0;
+ private static final int P_31 = 1;
+ private static final int P_32 = 1;
+ private static final int P_33 = P_31 ^ 1;
+ private static final int P_34 = 1;
+
+ /* Primitive polynomial for GF(256) */
+ private static final int GF256_FDBK = 0x169;
+ private static final int GF256_FDBK_2 = GF256_FDBK / 2;
+ private static final int GF256_FDBK_4 = GF256_FDBK / 4;
+
+ private static final int RS_GF_FDBK = 0x14D; // field generator
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private static final int ROUNDS = 16;
+ private static final int MAX_ROUNDS = 16; // bytes = 128 bits
+ private static final int BLOCK_SIZE = 16; // bytes = 128 bits
+ private static final int MAX_KEY_BITS = 256;
+
+ private static final int INPUT_WHITEN=0;
+ private static final int OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
+ private static final int ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
+
+ private static final int TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
+
+ private static final int SK_STEP = 0x02020202;
+ private static final int SK_BUMP = 0x01010101;
+ private static final int SK_ROTL = 9;
+
+ private boolean encrypting = false;
+
+ private int[] gMDS0 = new int[MAX_KEY_BITS];
+ private int[] gMDS1 = new int[MAX_KEY_BITS];
+ private int[] gMDS2 = new int[MAX_KEY_BITS];
+ private int[] gMDS3 = new int[MAX_KEY_BITS];
+
+ /**
+ * gSubKeys[] and gSBox[] are eventually used in the
+ * encryption and decryption methods.
+ */
+ private int[] gSubKeys;
+ private int[] gSBox;
+
+ private int k64Cnt = 0;
+
+ private byte[] workingKey = null;
+
+ public TwofishEngine()
+ {
+ // calculate the MDS matrix
+ int[] m1 = new int[2];
+ int[] mX = new int[2];
+ int[] mY = new int[2];
+ int j;
+
+ for (int i=0; i< MAX_KEY_BITS ; i++)
+ {
+ j = P[0][i] & 0xff;
+ m1[0] = j;
+ mX[0] = Mx_X(j) & 0xff;
+ mY[0] = Mx_Y(j) & 0xff;
+
+ j = P[1][i] & 0xff;
+ m1[1] = j;
+ mX[1] = Mx_X(j) & 0xff;
+ mY[1] = Mx_Y(j) & 0xff;
+
+ gMDS0[i] = m1[P_00] | mX[P_00] << 8 |
+ mY[P_00] << 16 | mY[P_00] << 24;
+
+ gMDS1[i] = mY[P_10] | mY[P_10] << 8 |
+ mX[P_10] << 16 | m1[P_10] << 24;
+
+ gMDS2[i] = mX[P_20] | mY[P_20] << 8 |
+ m1[P_20] << 16 | mY[P_20] << 24;
+
+ gMDS3[i] = mX[P_30] | m1[P_30] << 8 |
+ mY[P_30] << 16 | mX[P_30] << 24;
+ }
+ }
+
+ /**
+ * initialise a Twofish cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.workingKey = ((KeyParameter)params).getKey();
+ this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
+ setKey(this.workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Twofish init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Twofish";
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Twofish not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ if (this.workingKey != null)
+ {
+ setKey(this.workingKey);
+ }
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ private void setKey(byte[] key)
+ {
+ int[] k32e = new int[MAX_KEY_BITS/64]; // 4
+ int[] k32o = new int[MAX_KEY_BITS/64]; // 4
+
+ int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
+ gSubKeys = new int[TOTAL_SUBKEYS];
+
+ if (k64Cnt < 1)
+ {
+ throw new IllegalArgumentException("Key size less than 64 bits");
+ }
+
+ if (k64Cnt > 4)
+ {
+ throw new IllegalArgumentException("Key size larger than 256 bits");
+ }
+
+ /*
+ * k64Cnt is the number of 8 byte blocks (64 chunks)
+ * that are in the input key. The input key is a
+ * maximum of 32 bytes (256 bits), so the range
+ * for k64Cnt is 1..4
+ */
+ for (int i=0; i
+ * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+ *
+ * where a = primitive root of field generator 0x14D
+ */
+ private int RS_rem(int x)
+ {
+ int b = (x >>> 24) & 0xff;
+ int g2 = ((b << 1) ^
+ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+ int g3 = ((b >>> 1) ^
+ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)) ^ g2 ;
+ return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+ }
+
+ private int LFSR1(int x)
+ {
+ return (x >> 1) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+ }
+
+ private int LFSR2(int x)
+ {
+ return (x >> 2) ^
+ (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+ }
+
+ private int Mx_X(int x)
+ {
+ return x ^ LFSR2(x);
+ } // 5B
+
+ private int Mx_Y(int x)
+ {
+ return x ^ LFSR1(x) ^ LFSR2(x);
+ } // EF
+
+ private int b0(int x)
+ {
+ return x & 0xff;
+ }
+
+ private int b1(int x)
+ {
+ return (x >>> 8) & 0xff;
+ }
+
+ private int b2(int x)
+ {
+ return (x >>> 16) & 0xff;
+ }
+
+ private int b3(int x)
+ {
+ return (x >>> 24) & 0xff;
+ }
+
+ private int Fe32_0(int x)
+ {
+ return gSBox[ 0x000 + 2*(x & 0xff) ] ^
+ gSBox[ 0x001 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 16) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 24) & 0xff) ];
+ }
+
+ private int Fe32_3(int x)
+ {
+ return gSBox[ 0x000 + 2*((x >>> 24) & 0xff) ] ^
+ gSBox[ 0x001 + 2*(x & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 16) & 0xff) ];
+ }
+
+ private int BytesTo32Bits(byte[] b, int p)
+ {
+ return ((b[p] & 0xff)) |
+ ((b[p+1] & 0xff) << 8) |
+ ((b[p+2] & 0xff) << 16) |
+ ((b[p+3] & 0xff) << 24);
+ }
+
+ private void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset] = (byte)in;
+ b[offset + 1] = (byte)(in >> 8);
+ b[offset + 2] = (byte)(in >> 16);
+ b[offset + 3] = (byte)(in >> 24);
+ }
+}
diff --git a/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
new file mode 100644
index 00000000..8a4d28ab
--- /dev/null
+++ b/src/java/KP2AKdbLibrary/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
@@ -0,0 +1,131 @@
+package org.bouncycastle.crypto.generators;
+
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.Digest;
+import org.bouncycastle.crypto.PBEParametersGenerator;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as usd by OpenSSL.
+ *