Remove spongycastle, use maven repos in zipsigner

This commit is contained in:
Daniel Martí 2015-11-14 17:09:55 +01:00
parent 51676bf255
commit 4e81aba841
2161 changed files with 8 additions and 336721 deletions

View File

@ -1,22 +0,0 @@
<html>
<body bgcolor=#ffffff>
Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
<p>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
<p>
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</body>
</html>

View File

@ -1,13 +0,0 @@
subprojects {
apply plugin: 'java'
group = 'com.madgag.spongycastle'
repositories {
mavenCentral()
}
sourceCompatibility = 1.5
targetCompatibility = 1.5
version = '1.51.0.0'
}

View File

@ -1,5 +0,0 @@
apply plugin: 'java'
sourceCompatibility = 1.5
targetCompatibility = 1.5
version = '1.51.0.0'

View File

@ -1,56 +0,0 @@
package java.io;
public class FilterInputStream extends InputStream
{
protected InputStream in;
protected FilterInputStream(InputStream underlying)
{
in = underlying;
}
public int read() throws IOException
{
return in.read();
}
public int read(byte[] b) throws IOException
{
return read(b, 0, b.length);
}
public int read(byte[] b, int offset, int length) throws IOException
{
return in.read(b, offset, length);
}
public long skip(long n) throws IOException
{
return in.skip(n);
}
public int available() throws IOException
{
return in.available();
}
public void close() throws IOException
{
in.close();
}
public void mark(int readlimit)
{
in.mark(readlimit);
}
public void reset() throws IOException
{
in.reset();
}
public boolean markSupported()
{
return in.markSupported();
}
}

View File

@ -1,39 +0,0 @@
package java.io;
public class FilterOutputStream extends OutputStream
{
protected OutputStream out;
protected FilterOutputStream(OutputStream underlying)
{
out = underlying;
}
public void write(int b) throws IOException
{
out.write(b);
}
public void write(byte[] b) throws IOException
{
write(b, 0, b.length);
}
public void write(byte[] b, int offset, int length) throws IOException
{
for (int i = 0; i < length; i++)
{
write(b[offset + i]);
}
}
public void flush() throws IOException
{
out.flush();
}
public void close() throws IOException
{
out.close();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,141 +0,0 @@
package java.security;
import java.util.Random;
import org.spongycastle.crypto.digests.SHA1Digest;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.prng.RandomGenerator;
import org.spongycastle.crypto.prng.DigestRandomGenerator;
/**
* An implementation of SecureRandom specifically for the light-weight API, JDK
* 1.0, and the J2ME. Random generation is based on the traditional SHA1 with
* counter. Calling setSeed will always increase the entropy of the hash.
* <p>
* <b>Do not use this class without calling setSeed at least once</b>! There
* are some example seed generators in the org.spongycastle.prng package.
*/
public class SecureRandom extends java.util.Random
{
// Note: all objects of this class should be deriving their random data from
// a single generator appropriate to the digest being used.
private static final RandomGenerator sha1Generator = new DigestRandomGenerator(new SHA1Digest());
private static final RandomGenerator sha256Generator = new DigestRandomGenerator(new SHA256Digest());
protected RandomGenerator generator;
// public constructors
public SecureRandom()
{
this(sha1Generator);
setSeed(System.currentTimeMillis());
}
public SecureRandom(byte[] inSeed)
{
this(sha1Generator);
setSeed(inSeed);
}
protected SecureRandom(
RandomGenerator generator)
{
super(0);
this.generator = generator;
}
// protected constructors
// protected SecureRandom(SecureRandomSpi srs, Provider provider);
// public class methods
public static SecureRandom getInstance(String algorithm)
{
if (algorithm.equals("SHA1PRNG"))
{
return new SecureRandom(sha1Generator);
}
if (algorithm.equals("SHA256PRNG"))
{
return new SecureRandom(sha256Generator);
}
return new SecureRandom(); // follow old behaviour
}
public static SecureRandom getInstance(String algorithm, String provider)
{
return getInstance(algorithm);
}
public static byte[] getSeed(int numBytes)
{
byte[] rv = new byte[numBytes];
sha1Generator.addSeedMaterial(System.currentTimeMillis());
sha1Generator.nextBytes(rv);
return rv;
}
// public instance methods
public byte[] generateSeed(int numBytes)
{
byte[] rv = new byte[numBytes];
nextBytes(rv);
return rv;
}
// public final Provider getProvider();
public void setSeed(byte[] inSeed)
{
generator.addSeedMaterial(inSeed);
}
// public methods overriding random
public void nextBytes(byte[] bytes)
{
generator.nextBytes(bytes);
}
public void setSeed(long rSeed)
{
if (rSeed != 0) // to avoid problems with Random calling setSeed in construction
{
generator.addSeedMaterial(rSeed);
}
}
public int nextInt()
{
byte[] intBytes = new byte[4];
nextBytes(intBytes);
int result = 0;
for (int i = 0; i < 4; i++)
{
result = (result << 8) + (intBytes[i] & 0xff);
}
return result;
}
protected final int next(int numBits)
{
int size = (numBits + 7) / 8;
byte[] bytes = new byte[size];
nextBytes(bytes);
int result = 0;
for (int i = 0; i < size; i++)
{
result = (result << 8) + (bytes[i] & 0xff);
}
return result & ((1 << numBits) - 1);
}
}

View File

@ -1,261 +0,0 @@
package java.util;
public abstract class AbstractCollection
implements Collection
{
protected AbstractCollection()
{
}
public abstract Iterator iterator();
public abstract int size();
public boolean isEmpty()
{
return size() == 0;
}
public boolean contains(Object o)
{
Iterator it = iterator();
while (it.hasNext())
{
Object e = it.next();
if (o == null)
{
if (e == null)
{
return true;
}
}
else
{
if (o.equals(e))
{
return true;
}
}
}
return false;
}
public Object[] toArray()
{
Object[] arObjects = new Object[size()];
Iterator it = iterator();
int i = 0;
while (it.hasNext())
{
arObjects[i++] = it.next();
}
return arObjects;
}
public Object[] toArray(Object[] a)
throws NullPointerException, ArrayStoreException
//TODO: Check if this is realy compatible to SUN!!!
{
if (a == null)
{
throw new NullPointerException();
}
if (isEmpty())
{
return a;
}
Object[] arObjects = null;
int size = size();
if (a.length < size)
{
Iterator it = iterator();
Object o = it.next();
if (o == null) //no object or object is null
{
throw new ArrayStoreException(); //correct ?
}
throw new ArrayStoreException("please pass array of correct size");
}
else
{
arObjects = a;
if (a.length > size)
{
arObjects[size] = null;
}
}
Iterator it = iterator();
int i = 0;
while (it.hasNext())
{
Object o = it.next();
arObjects[i++] = o;
}
return arObjects;
}
public boolean add(Object o)
throws RuntimeException, NullPointerException, ClassCastException, IllegalArgumentException
{
throw new RuntimeException();
}
public boolean remove(Object o)
throws RuntimeException
{
Iterator it = iterator();
while (it.hasNext())
{
Object e = it.next();
if (o == null)
{
if (e == null)
{
try
{
it.remove();
}
catch (RuntimeException ue)
{
throw ue;
}
return true;
}
}
else
{
if (o.equals(e))
{
try
{
it.remove();
}
catch (RuntimeException ue)
{
throw ue;
}
return true;
}
}
}
return false;
}
public boolean containsAll(Collection c)
{
Iterator it = c.iterator();
while (it.hasNext())
{
if (!contains(it.next()))
{
return false;
}
}
return true;
}
public boolean addAll(Collection c)
throws RuntimeException
{
Iterator it = c.iterator();
boolean ret = false;
while (it.hasNext())
{
try
{
ret |= add(it.next());
}
catch (RuntimeException ue)
{
throw ue;
}
}
return ret;
}
public boolean removeAll(Collection c)
throws RuntimeException
{
Iterator it = iterator();
boolean ret = false;
while (it.hasNext())
{
if (c.contains(it.next()))
{
try
{
it.remove();
ret = true;
}
catch (RuntimeException ue)
{
throw ue;
}
}
}
return ret;
}
public boolean retainAll(Collection c)
throws RuntimeException
{
Iterator it = iterator();
boolean ret = false;
while (it.hasNext())
{
if (!c.contains(it.next()))
{
try
{
it.remove();
ret = true;
}
catch (RuntimeException ue)
{
throw ue;
}
}
}
return ret;
}
public void clear()
throws RuntimeException
{
Iterator it = iterator();
while (it.hasNext())
{
try
{
it.next();
it.remove();
}
catch (RuntimeException ue)
{
throw ue;
}
}
}
public String toString()
{
StringBuffer ret = new StringBuffer("[");
Iterator it = iterator();
if (it.hasNext())
{
ret.append(String.valueOf(it.next()));
}
while (it.hasNext())
{
ret.append(", ");
ret.append(String.valueOf(it.next()));
}
ret.append("]");
return ret.toString();
}
}

View File

@ -1,304 +0,0 @@
package java.util;
public abstract class AbstractList
extends AbstractCollection
implements List
{
protected AbstractList al = this;
protected AbstractList()
{
}
public boolean add(Object o)
throws RuntimeException, ClassCastException, IllegalArgumentException
{
try
{
add(size(), o);
return true;
}
catch (RuntimeException ue)
{
throw ue;
}
}
public abstract Object get(int index)
throws IndexOutOfBoundsException;
public Object set(int index, Object element)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
{
throw new RuntimeException();
}
public void add(int index, Object element)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
{
throw new RuntimeException();
}
public Object remove(int index)
throws RuntimeException, IndexOutOfBoundsException
{
Object o = get(index);
removeRange(index, index + 1);
return o;
}
public int indexOf(Object o)
{
ListIterator li = listIterator();
Object e;
while (li.hasNext())
{
int index = li.nextIndex();
e = li.next();
if (o == null)
{
if (e == null)
{
return index;
}
}
else
{
if (o.equals(e))
{
return index;
}
}
}
return -1;
}
public int lastIndexOf(Object o)
{
ListIterator li = listIterator(size());
while (li.hasPrevious())
{
int index = li.previousIndex();
Object e = li.previous();
if (o == null)
{
if (e == null)
{
return index;
}
}
else
{
if (o.equals(e))
{
return index;
}
}
}
return -1;
}
public void clear()
throws RuntimeException
{
try
{
removeRange(0, size());
}
catch (RuntimeException ue)
{
throw ue;
}
}
public boolean addAll(int index, Collection c)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException
{
Iterator it = c.iterator();
boolean ret = false;
while (it.hasNext())
{
try
{
add(index++, it.next());
ret = true;
}
catch (RuntimeException ue)
{
throw ue;
}
}
return ret;
}
public Iterator iterator()
{
return new AbstractListIterator(this, 0);
}
public ListIterator listIterator()
{
return listIterator(0);
}
public ListIterator listIterator(int index)
throws IndexOutOfBoundsException
{
if (index < 0 || index > size())
{
throw new IndexOutOfBoundsException();
}
return new AbstractListListIterator(this, index);
}
public List subList(int fromIndex, int toIndex)
throws IndexOutOfBoundsException, IllegalArgumentException
{
if (fromIndex < 0 || toIndex > size())
{
throw new IndexOutOfBoundsException();
}
if (fromIndex > toIndex)
{
throw new IllegalArgumentException();
}
return (List)new Sublist(this, fromIndex, toIndex);
}
public boolean equals(Object o)
{
if (o == this)
{
return true;
}
if (!(o instanceof List))
{
return false;
}
Iterator it1 = iterator();
Iterator it2 = ((List)o).iterator();
while (it1.hasNext())
{
if (!it2.hasNext())
{
return false;
}
Object e1 = it1.next();
Object e2 = it2.next();
if (e1 == null)
{
if (e2 != null)
{
return false;
}
}
if (!e1.equals(e2))
{
return false;
}
}
return true;
}
public int hashCode()
{
int hashCode = 1;
Iterator it = iterator();
while (it.hasNext())
{
Object o = it.next();
hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
}
return hashCode;
}
protected void removeRange(int fromIndex, int toIndex)
{
if (fromIndex == toIndex)
{
return;
}
ListIterator li = listIterator(fromIndex);
int i = fromIndex;
do
{
li.next();
li.remove();
i++;
}
while (li.hasNext() && i < toIndex);
}
private class AbstractListIterator
implements Iterator
{
AbstractList m_al = null;
int m_nextIndex = 0;
public AbstractListIterator(AbstractList al, int index)
{
m_al = al;
m_nextIndex = index;
}
public boolean hasNext()
{
return m_nextIndex < m_al.size();
}
public Object next()
{
return m_al.get(m_nextIndex++);
}
public void remove()
{
m_al.remove(m_nextIndex - 1);
}
}
private class AbstractListListIterator
extends AbstractListIterator
implements ListIterator
{
public AbstractListListIterator(AbstractList al, int index)
{
super(al, index);
}
public boolean hasPrevious()
{
return m_nextIndex > 0;
}
public Object previous()// throws NoSuchElementException;
{
return m_al.get(--m_nextIndex);
}
public int nextIndex()
{
return m_nextIndex;
}
public int previousIndex()
{
return m_nextIndex - 1;
}
public void set(Object o) //throws RuntimeException, ClassCastException, IllegalArgumentException,IllegalStateException;
{
m_al.set(m_nextIndex - 1, o);
}
public void add(Object o)// throws RuntimeException, ClassCastException, IllegalArgumentException;
{
m_al.add(m_nextIndex - 1, o);
}
}
}

View File

@ -1,173 +0,0 @@
package java.util;
public abstract class AbstractMap
implements Map
{
protected AbstractMap()
{
}
public int size()
{
return entrySet().size();
}
public boolean isEmpty()
{
return size() == 0;
}
public boolean containsValue(Object value)
{
Iterator it = entrySet().iterator();
while (it.hasNext())
{
Map.Entry v = (Map.Entry)it.next();
if (value == null)
{
if (v.getValue() == null)
{
return true;
}
}
else
{
if (value.equals(v.getValue()))
{
return true;
}
}
}
return false;
}
public boolean containsKey(Object key)
throws ClassCastException, NullPointerException
{
Iterator it = entrySet().iterator();
while (it.hasNext())
{
Map.Entry v = (Map.Entry)it.next();
if (key == null)
{
if (v.getKey() == null)
{
return true;
}
}
else
{
if (key.equals(v.getKey()))
{
return true;
}
}
}
return false;
}
public Object get(Object key)
throws ClassCastException, NullPointerException
{
Iterator it = entrySet().iterator();
while (it.hasNext())
{
Map.Entry v = (Map.Entry)it.next();
if (key == null)
{
if (v.getKey() == null)
{
return v.getValue();
}
}
else
{
if (key.equals(v.getKey()))
{
return v.getValue();
}
}
}
return null;
}
public Object put(Object key, Object value)
throws RuntimeException
{
throw new RuntimeException();
}
public Object remove(Object key)
{
Iterator it = entrySet().iterator();
Object o = null;
while (it.hasNext())
{
Map.Entry v = (Map.Entry)it.next();
if (key == null)
{
if (v.getKey() == null)
{
o = v.getValue();
it.remove();
return o;
}
}
else
{
if (key.equals(v.getKey()))
{
o = v.getValue();
it.remove();
return o;
}
}
}
return null;
}
public void putAll(Map t)
{
Iterator it = t.entrySet().iterator();
while (it.hasNext())
{
Map.Entry v = (Map.Entry)it.next();
put(v.getKey(), v.getValue());
}
}
public void clear()
{
entrySet().clear();
}
public Set keySet()
{
throw new RuntimeException("no keySet in AbstractMap()");
}
public Collection values()
{
throw new RuntimeException("no values in AbstractMap()");
}
public abstract Set entrySet();
public boolean equals(Object o)
{
throw new RuntimeException("no equals in AbstractMap()");
}
public int hashCode()
{
throw new RuntimeException("no hashCode in AbstractMap()");
}
public String toString()
{
throw new RuntimeException("no toString in AbstractMap()");
}
}

View File

@ -1,46 +0,0 @@
package java.util;
public abstract class AbstractSet
extends AbstractCollection
implements Set
{
protected AbstractSet()
{
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null)
{
return false;
}
if (!(o instanceof Set))
{
return false;
}
if (((Set)o).size() != size())
{
return false;
}
return containsAll((Collection)o);
}
public int hashCode()
{
int hashCode = 0;
Iterator it = iterator();
while (it.hasNext())
{
Object o = it.next();
if (o != null)
{
hashCode += o.hashCode();
}
}
return hashCode;
}
}

View File

@ -1,107 +0,0 @@
package java.util;
public class ArrayList extends AbstractList
implements List
{
Vector m_Vector=null;
public ArrayList()
{
m_Vector=new Vector();
}
public ArrayList(Collection c)
{
m_Vector=new Vector((int)(c.size()*1.1));
addAll(c);
}
public ArrayList(int initialCapacity)
{
m_Vector=new Vector(initialCapacity);
}
public void trimToSize()
{
m_Vector.trimToSize();
}
public void ensureCapacity(int minCapacity)
{
m_Vector.ensureCapacity(minCapacity);
}
public int size()
{
return m_Vector.size();
}
public boolean contains(Object elem)
{
return m_Vector.contains(elem);
}
public int indexOf(Object elem)
{
return m_Vector.indexOf(elem);
}
public int lastIndexOf(Object elem)
{
return m_Vector.lastIndexOf(elem);
}
public Object clone()
{
ArrayList al=new ArrayList(this);
return al;
}
public Object[] toArray()
{
Object[] o=new Object[m_Vector.size()];
m_Vector.copyInto(o);
return o;
}
public Object get(int index)
{
return m_Vector.elementAt(index);
}
public Object set(int index,Object elem)
{
Object o=m_Vector.elementAt(index);
m_Vector.setElementAt(elem,index);
return o;
}
public boolean add(Object o)
{
m_Vector.addElement(o);
return true;
}
public void add(int index,Object elem)
{
m_Vector.insertElementAt(elem,index);
}
public Object remove(int index)
{
Object o=m_Vector.elementAt(index);
m_Vector.removeElementAt(index);
return o;
}
public void clear()
{
m_Vector.removeAllElements();
}
}

View File

@ -1,118 +0,0 @@
package java.util;
public class Arrays
{
private Arrays()
{
}
public static void fill(byte[] ret, byte v)
{
for (int i = 0; i != ret.length; i++)
{
ret[i] = v;
}
}
public static boolean equals(byte[] a, byte[] a2)
{
if (a == a2)
{
return true;
}
if (a == null || a2 == null)
{
return false;
}
int length = a.length;
if (a2.length != length)
{
return false;
}
for (int i = 0; i < length; i++)
{
if (a[i] != a2[i])
{
return false;
}
}
return true;
}
public static List asList(Object[] a)
{
return new ArrayList(a);
}
private static class ArrayList
extends AbstractList
{
private Object[] a;
ArrayList(Object[] array)
{
a = array;
}
public int size()
{
return a.length;
}
public Object[] toArray()
{
Object[] tmp = new Object[a.length];
System.arraycopy(a, 0, tmp, 0, tmp.length);
return tmp;
}
public Object get(int index)
{
return a[index];
}
public Object set(int index, Object element)
{
Object oldValue = a[index];
a[index] = element;
return oldValue;
}
public int indexOf(Object o)
{
if (o == null)
{
for (int i = 0; i < a.length; i++)
{
if (a[i] == null)
{
return i;
}
}
}
else
{
for (int i = 0; i < a.length; i++)
{
if (o.equals(a[i]))
{
return i;
}
}
}
return -1;
}
public boolean contains(Object o)
{
return indexOf(o) != -1;
}
}
}

View File

@ -1,21 +0,0 @@
package java.util;
public interface Collection
{
public boolean add(Object o) throws RuntimeException,ClassCastException,IllegalArgumentException;
public boolean addAll(Collection c) throws RuntimeException,ClassCastException,IllegalArgumentException;
public void clear() throws RuntimeException;
public boolean contains(Object o);
public boolean containsAll(Collection c);
public boolean equals(Object o);
public int hashCode();
public boolean isEmpty();
public Iterator iterator();
public /*SK13*/boolean remove(Object o) throws RuntimeException;
public boolean removeAll(Collection c) throws RuntimeException;
public boolean retainAll(Collection c) throws RuntimeException;
public int size();
public Object[] toArray();
public Object[] toArray(Object[] a) throws ArrayStoreException;
}

View File

@ -1,365 +0,0 @@
package java.util;
public class Collections
{
public static List EMPTY_LIST = new ArrayList();
private Collections()
{
}
public static Collection unmodifiableCollection(Collection c)
{
return new UnmodifiableCollection(c);
}
static class UnmodifiableCollection
implements Collection
{
Collection c;
UnmodifiableCollection(Collection c)
{
this.c = c;
}
public int size()
{
return c.size();
}
public boolean isEmpty()
{
return c.isEmpty();
}
public boolean contains(Object o)
{
return c.contains(o);
}
public Object[] toArray()
{
return c.toArray();
}
public Object[] toArray(Object[] a)
{
return c.toArray(a);
}
public Iterator iterator()
{
return new Iterator()
{
Iterator i = c.iterator();
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
return i.next();
}
public void remove()
{
throw new RuntimeException();
}
};
}
public boolean add(Object o)
{
throw new RuntimeException();
}
public boolean remove(Object o)
{
throw new RuntimeException();
}
public boolean containsAll(Collection coll)
{
return c.containsAll(coll);
}
public boolean addAll(Collection coll)
{
throw new RuntimeException();
}
public boolean removeAll(Collection coll)
{
throw new RuntimeException();
}
public boolean retainAll(Collection coll)
{
throw new RuntimeException();
}
public void clear()
{
throw new RuntimeException();
}
public String toString()
{
return c.toString();
}
}
public static Set unmodifiableSet(Set s)
{
return new UnmodifiableSet(s);
}
static class UnmodifiableSet
extends UnmodifiableCollection
implements Set
{
UnmodifiableSet(Set s)
{
super(s);
}
public boolean equals(Object o)
{
return c.equals(o);
}
public int hashCode()
{
return c.hashCode();
}
}
public static Map unmodifiableMap(Map map)
{
return new UnmodifiableMap(map);
}
static class UnmodifiableMap
implements Map
{
private Map map;
UnmodifiableMap(Map map)
{
this.map = map;
}
public int size()
{
return map.size();
}
public boolean isEmpty()
{
return map.isEmpty();
}
public boolean containsKey(Object key)
throws ClassCastException, NullPointerException
{
return map.containsKey(key);
}
public boolean containsValue(Object value)
{
return map.containsValue(value);
}
public Object get(Object key)
throws ClassCastException, NullPointerException
{
return map.get(key);
}
public Object put(Object key, Object value)
throws RuntimeException, ClassCastException, IllegalArgumentException, NullPointerException
{
throw new RuntimeException("unsupported operation - map unmodifiable");
}
public Object remove(Object key)
throws RuntimeException
{
throw new RuntimeException("unsupported operation - map unmodifiable");
}
public void putAll(Map t)
throws RuntimeException, ClassCastException, IllegalArgumentException, NullPointerException
{
throw new RuntimeException("unsupported operation - map unmodifiable");
}
public void clear()
throws RuntimeException
{
throw new RuntimeException("unsupported operation - map unmodifiable");
}
public Set keySet()
{
return map.keySet();
}
public Collection values()
{
return map.values();
}
public Set entrySet()
{
return map.entrySet();
}
}
public static List unmodifiableList(List list)
{
return new UnmodifiableList(list);
}
static class UnmodifiableList
extends UnmodifiableCollection
implements List
{
private List list;
UnmodifiableList(List list)
{
super(list);
this.list = list;
}
public boolean equals(Object o)
{
return list.equals(o);
}
public int hashCode()
{
return list.hashCode();
}
public Object get(int index)
{
return list.get(index);
}
public Object set(int index, Object element)
{
throw new RuntimeException();
}
public void add(int index, Object element)
{
throw new RuntimeException();
}
public Object remove(int index)
{
throw new RuntimeException();
}
public int indexOf(Object o)
{
return list.indexOf(o);
}
public int lastIndexOf(Object o)
{
return list.lastIndexOf(o);
}
public boolean addAll(int index, Collection c)
{
throw new RuntimeException();
}
public ListIterator listIterator()
{
return listIterator(0);
}
public ListIterator listIterator(final int index)
{
return new ListIterator()
{
ListIterator i = list.listIterator(index);
public boolean hasNext()
{
return i.hasNext();
}
public Object next()
{
return i.next();
}
public boolean hasPrevious()
{
return i.hasPrevious();
}
public Object previous()
{
return i.previous();
}
public int nextIndex()
{
return i.nextIndex();
}
public int previousIndex()
{
return i.previousIndex();
}
public void remove()
{
throw new RuntimeException();
}
public void set(Object o)
{
throw new RuntimeException();
}
public void add(Object o)
{
throw new RuntimeException();
}
};
}
public List subList(int fromIndex, int toIndex)
{
return new UnmodifiableList(list.subList(fromIndex, toIndex));
}
}
public static Enumeration enumeration(final Collection c)
{
return new Enumeration()
{
Iterator i = c.iterator();
public boolean hasMoreElements()
{
return i.hasNext();
}
public Object nextElement()
{
return i.next();
}
};
}
}

View File

@ -1,279 +0,0 @@
package java.util;
public class HashMap extends AbstractMap{
//////////////////////////////////////////////////////////////
///// innere Klasse Null ////////////////////////////////////
//////////////////////////////////////////////////////////////
public class Null extends Object
{
public Null()
{
}
public String toString()
{
return "Nullobject";
}
}
//////////////////////////////////////////////////////////////
///// innere Klasse innerSet ////////////////////////////////////
//////////////////////////////////////////////////////////////
class ISet extends AbstractSet implements java.util.Set
{
Vector vec = null;
public ISet()
{
vec = new Vector();
}
public boolean add(Object o)
{
vec.addElement(o);
return true;
}
public int size()
{
return vec.size();
}
public Iterator iterator()
{
return new IIterator(vec);
}
}
//////////////////////////////////////////////////////////////
///// innere Klasse Iterator ////////////////////////////////////
//////////////////////////////////////////////////////////////
class IIterator implements java.util.Iterator
{
int index = 0;
Vector vec = null;
public IIterator(Vector ve)
{
vec = ve;
}
public boolean hasNext()
{
if (vec.size() > index) return true;
return false;
}
public Object next()
{
Object o = vec.elementAt(index);
if (o==Nullobject) o=null;
index++;
return o;
}
public void remove()
{
index--;
vec.removeElementAt(index);
}
}
//////////////////////////////////////////////////////////////
///// innere Klasse Entry ////////////////////////////////////
//////////////////////////////////////////////////////////////
class Entry implements Map.Entry
{
public Object key=null;
public Object value=null;
public Entry(Object ke,Object valu)
{
key = ke;
value = valu;
}
public boolean equals(Object o)
{
if (value == ((Entry)o).value && key == ((Entry)o).key ) return true;
else return false;
}
public Object getValue()
{
return value;
}
public Object getKey()
{
return (Object)key;
}
public int hashCode()
{
return value.hashCode() + key.hashCode();
}
public Object setValue(Object valu)
{
value = (String)valu;
return this;
}
}
////////////////////////////////////////////////////////////////////
private Hashtable m_HashTable=null;
private Null Nullobject = null;
public HashMap()
{
Nullobject = new Null();
m_HashTable=new Hashtable();
}
public HashMap(int initialCapacity)
{
Nullobject = new Null();
m_HashTable=new Hashtable(initialCapacity);
}
public HashMap(Map t)
{
Nullobject = new Null();
m_HashTable=new Hashtable();
this.putAll(t);
}
public void clear()
{
m_HashTable.clear();
}
public Object clone()
{
HashMap hm=new HashMap(this);
return hm;
}
public boolean containsKey(Object key)
{
if (key == null) key = Nullobject;
boolean b = m_HashTable.containsKey(key);
return b;
}
public boolean containsValue(Object value)
{
if (value == null ) value = Nullobject;
boolean b = m_HashTable.contains(value);
return b;
}
public Set entrySet()
{
Object Key = null;
ISet s = new ISet();
Enumeration en = m_HashTable.keys();
while (en.hasMoreElements())
{
Key = en.nextElement();
s.add(new Entry(Key,m_HashTable.get(Key)));
}
return s;
}
public Object get(Object key)
{
if (key==null) key= Nullobject;
Object o = m_HashTable.get(key);
if (o == Nullobject) o=null;
return o;
}
public boolean isEmpty()
{
return m_HashTable.isEmpty();
}
public Set keySet()
{
ISet s=new ISet();
Enumeration en = m_HashTable.keys();
while (en.hasMoreElements())
{
s.add(en.nextElement());
}
return s;
}
public Object put(Object key, Object value)
{
if (key==null) key=Nullobject;
if (value==null) value = Nullobject;
return m_HashTable.put(key,value);
}
public void putAll(Map m)
{
Iterator it = m.entrySet().iterator();
Object key=null;
Object value=null;
while (it.hasNext())
{
Map.Entry me = (Map.Entry)it.next();
if (me.getKey() == null) key = Nullobject;
else key= me.getKey();
if (me.getValue()==null) value = Nullobject;
else value = me.getValue();
m_HashTable.put(key,value);
}
}
public Object remove(Object key)
{
return m_HashTable.remove(key);
}
public int size()
{
return m_HashTable.size();
}
public Collection values()
{
ISet s=new ISet();
Enumeration en = m_HashTable.keys();
while (en.hasMoreElements())
{
Object Key = en.nextElement();
//s.add(((Map.Entry)m_HashTable.get(Key)).getValue());
s.add(m_HashTable.get(Key));
}
return s;
}
}

View File

@ -1,71 +0,0 @@
package java.util;
public class HashSet
extends AbstractSet
{
private HashMap m_HashMap = null;
public HashSet()
{
m_HashMap = new HashMap();
}
public HashSet(Collection c)
{
m_HashMap = new HashMap(Math.max(11, c.size() * 2));
addAll(c);
}
public HashSet(int initialCapacity)
{
m_HashMap = new HashMap(initialCapacity);
}
public Iterator iterator()
{
return (m_HashMap.keySet()).iterator();
}
public int size()
{
return m_HashMap.size();
}
public boolean contains(Object o)
{
return m_HashMap.containsKey(o);
}
public boolean add(Object o)
{
if (!m_HashMap.containsValue(o))
{
m_HashMap.put((Object)o, (Object)o);
return true;
}
return false;
}
public boolean remove(Object o)
{
return (m_HashMap.remove(o) != null);
}
public void clear()
{
m_HashMap.clear();
}
public Object clone()
{
HashSet hs = new HashSet();
hs.m_HashMap = (HashMap)m_HashMap.clone();
return hs;
}
}

View File

@ -1,9 +0,0 @@
package java.util;
public interface Iterator
{
public abstract boolean hasNext();
public abstract Object next() throws NoSuchElementException;
public abstract void remove() throws RuntimeException,IllegalStateException;
}

View File

@ -1,32 +0,0 @@
package java.util;
public interface List
extends Collection
{
void add(int index, Object element)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException;
boolean addAll(int index, Collection c)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException;
Object get(int index)
throws IndexOutOfBoundsException;
int indexOf(Object o);
int lastIndexOf(Object o);
ListIterator listIterator();
ListIterator listIterator(int index)
throws IndexOutOfBoundsException;
Object remove(int index)
throws RuntimeException, IndexOutOfBoundsException;
Object set(int index, Object element)
throws RuntimeException, ClassCastException, IllegalArgumentException, IndexOutOfBoundsException;
List subList(int fromIndex, int toIndex)
throws IndexOutOfBoundsException;
}

View File

@ -1,20 +0,0 @@
package java.util;
public interface ListIterator
extends Iterator
{
public boolean hasPrevious();
public Object previous()
throws NoSuchElementException;
public int nextIndex();
public int previousIndex();
public void set(Object o)
throws RuntimeException, ClassCastException, IllegalArgumentException, IllegalStateException;
public void add(Object o)
throws RuntimeException, ClassCastException, IllegalArgumentException;
}

View File

@ -1,54 +0,0 @@
package java.util;
public interface Map
{
public static interface Entry
{
public Object getKey();
public Object getValue();
public Object setValue(Object value)
throws RuntimeException, ClassCastException, IllegalArgumentException, NullPointerException;
public boolean equals(Object o);
public int hashCode();
}
public int size();
public boolean isEmpty();
public boolean containsKey(Object Key)
throws ClassCastException, NullPointerException;
public boolean containsValue(Object value);
public Object get(Object key)
throws ClassCastException, NullPointerException;
public Object put(Object key, Object value)
throws RuntimeException, ClassCastException, IllegalArgumentException, NullPointerException;
public Object remove(Object key)
throws RuntimeException;
public void putAll(Map t)
throws RuntimeException, ClassCastException, IllegalArgumentException, NullPointerException;
public void clear()
throws RuntimeException;
public Set keySet();
public Collection values();
public Set entrySet();
public boolean equals(Object o);
public int hashCode();
}

View File

@ -1,38 +0,0 @@
package java.util;
public interface Set
extends Collection
{
public int size();
public boolean isEmpty();
public boolean contains(Object o);
public Iterator iterator();
public Object[] toArray();
public Object[] toArray(Object[] a);
public boolean add(Object o);
public boolean remove(Object o);
public boolean containsAll(Collection c);
public boolean addAll(Collection c);
public boolean retainAll(Collection c);
public boolean removeAll(Collection c);
public void clear();
public boolean equals(Object o);
public int hashCode();
}

View File

@ -1,115 +0,0 @@
package java.util;
import java.util.Enumeration;
import java.util.NoSuchElementException;
public class StringTokenizer
implements Enumeration
{
private String s;
private String delims;
private boolean retDelims;
private int maxPos;
private int pos;
public StringTokenizer(String s, String delims)
{
this(s, delims, false);
}
public StringTokenizer(String s, String delims, boolean retDelims)
{
this.s = s;
this.delims = delims;
this.retDelims = retDelims;
this.maxPos = s.length();
}
public boolean hasMoreTokens()
{
if (retDelims)
{
return pos < maxPos;
}
else
{
int next = pos;
while (next < maxPos && isDelim(next))
{
next++;
}
return next < maxPos;
}
}
public String nextToken()
{
String tok;
if (pos == maxPos)
{
throw new NoSuchElementException("no more tokens");
}
if (retDelims)
{
if (isDelim(pos))
{
tok = s.substring(pos, pos + 1);
pos++;
return tok;
}
}
while (pos < maxPos && isDelim(pos))
{
pos++;
}
int start = pos;
while (pos < maxPos && !isDelim(pos))
{
pos++;
}
if (pos < maxPos)
{
tok = s.substring(start, pos);
}
else
{
tok = s.substring(start);
}
return tok;
}
public boolean hasMoreElements()
{
return hasMoreTokens();
}
public Object nextElement()
{
return nextToken();
}
private boolean isDelim(int index)
{
char c = s.charAt(index);
for (int i = 0; i != delims.length(); i++)
{
if (delims.charAt(i) == c)
{
return true;
}
}
return false;
}
}

View File

@ -1,142 +0,0 @@
package java.util;
public class Sublist
extends AbstractList
{
AbstractList m_al = null;
int m_fromIndex = 0;
int m_toIndex = 0;
int size = 0;
public Sublist(AbstractList ali, int fromIndex, int toIndex)
{
m_al = ali;
m_toIndex = toIndex;
m_fromIndex = fromIndex;
size = size();
}
public Object set(int index, Object o)
{
if (index < size)
{
o = m_al.set(index + m_fromIndex, o);
if (o != null)
{
size++;
m_toIndex++;
}
return o;
}
else
{
throw new IndexOutOfBoundsException();
}
}
public Object get(int index)
throws IndexOutOfBoundsException
{
if (index < size)
{
return m_al.get(index + m_fromIndex);
}
else
{
throw new IndexOutOfBoundsException();
}
}
public void add(int index, Object o)
{
if (index <= size)
{
m_al.add(index + m_fromIndex, o);
m_toIndex++;
size++;
}
else
{
throw new IndexOutOfBoundsException();
}
}
public Object remove(int index, Object o)
{
if (index < size)
{
Object ob = m_al.remove(index + m_fromIndex);
if (ob != null)
{
m_toIndex--;
size--;
}
return ob;
}
else
{
throw new IndexOutOfBoundsException();
}
}
public boolean addAll(int index, Collection c)
{
if (index < size)
{
boolean bool = m_al.addAll(index + m_fromIndex, c);
if (bool)
{
int lange = c.size();
m_toIndex = m_toIndex + lange;
size = size + lange;
}
return bool;
}
else
{
throw new IndexOutOfBoundsException();
}
}
public boolean addAll(Collection c)
{
boolean bool = m_al.addAll(m_toIndex, c);
if (bool)
{
int lange = c.size();
m_toIndex = m_toIndex + lange;
size = size + lange;
}
return bool;
}
public void removeRange(int from, int to)
{
if ((from <= to) && (from <= size) && (to <= size))
{
m_al.removeRange(from, to);
int lange = to - from;
m_toIndex = m_toIndex - lange;
size = size - lange;
}
else
{
if (from > to)
{
throw new IllegalArgumentException();
}
else
{
throw new IndexOutOfBoundsException();
}
}
}
public int size()
{
return (m_toIndex - m_fromIndex);
}
}

View File

@ -1,260 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.util.Date;
import java.util.TimeZone;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.Strings;
/**
* Generalized time object.
*/
public class ASN1GeneralizedTime
extends ASN1Primitive
{
private byte[] time;
/**
* return a generalized time from the passed in object
*
* @exception IllegalArgumentException if the object cannot be converted.
*/
public static ASN1GeneralizedTime getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1GeneralizedTime)
{
return (ASN1GeneralizedTime)obj;
}
if (obj instanceof ASN1GeneralizedTime)
{
return new ASN1GeneralizedTime(((ASN1GeneralizedTime)obj).time);
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return a Generalized Time object from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
*/
public static ASN1GeneralizedTime getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1GeneralizedTime)
{
return getInstance(o);
}
else
{
return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
}
}
/**
* The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
* for local time, or Z|[+|-]HHMM on the end, for difference between local
* time and UTC time. The fractional second amount f must consist of at
* least one number with trailing zeroes removed.
*
* @param time the time string.
* @exception IllegalArgumentException if String is an illegal format.
*/
public ASN1GeneralizedTime(
String time)
{
char last = time.charAt(time.length() - 1);
if (last != 'Z' && !(last >= 0 && last <= '9'))
{
if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
{
throw new IllegalArgumentException("time needs to be in format YYYYMMDDHHMMSS[.f]Z or YYYYMMDDHHMMSS[.f][+-]HHMM");
}
}
this.time = Strings.toByteArray(time);
}
/**
* base constructer from a java.util.date object
*/
public ASN1GeneralizedTime(
Date time)
{
this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(time, false));
}
protected ASN1GeneralizedTime(Date date, boolean includeMillis)
{
this.time = Strings.toByteArray(DateFormatter.getGeneralizedTimeDateString(date, true));
}
ASN1GeneralizedTime(
byte[] bytes)
{
this.time = bytes;
}
/**
* Return the time.
* @return The time string as it appeared in the encoded object.
*/
public String getTimeString()
{
return Strings.fromByteArray(time);
}
/**
* return the time - always in the form of
* YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
* </pre>
* To read in the time and get a date which is compatible with our local
* time zone.
*/
public String getTime()
{
String stime = Strings.fromByteArray(time);
//
// standardise the format.
//
if (stime.charAt(stime.length() - 1) == 'Z')
{
return stime.substring(0, stime.length() - 1) + "GMT+00:00";
}
else
{
int signPos = stime.length() - 5;
char sign = stime.charAt(signPos);
if (sign == '-' || sign == '+')
{
return stime.substring(0, signPos)
+ "GMT"
+ stime.substring(signPos, signPos + 3)
+ ":"
+ stime.substring(signPos + 3);
}
else
{
signPos = stime.length() - 3;
sign = stime.charAt(signPos);
if (sign == '-' || sign == '+')
{
return stime.substring(0, signPos)
+ "GMT"
+ stime.substring(signPos)
+ ":00";
}
}
}
return stime + calculateGMTOffset();
}
private String calculateGMTOffset()
{
String sign = "+";
TimeZone timeZone = TimeZone.getDefault();
int offset = timeZone.getRawOffset();
if (offset < 0)
{
sign = "-";
offset = -offset;
}
int hours = offset / (60 * 60 * 1000);
int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
// try
// {
// if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
// {
// hours += sign.equals("+") ? 1 : -1;
// }
// }
// catch (ParseException e)
// {
// // we'll do our best and ignore daylight savings
// }
return "GMT" + sign + convert(hours) + ":" + convert(minutes);
}
private String convert(int time)
{
if (time < 10)
{
return "0" + time;
}
return Integer.toString(time);
}
public Date getDate()
{
return DateFormatter.fromGeneralizedTimeString(time);
}
private boolean hasFractionalSeconds()
{
for (int i = 0; i != time.length; i++)
{
if (time[i] == '.')
{
if (i == 14)
{
return true;
}
}
}
return false;
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
int length = time.length;
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeEncoded(BERTags.GENERALIZED_TIME, time);
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1GeneralizedTime))
{
return false;
}
return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
}
public int hashCode()
{
return Arrays.hashCode(time);
}
}

View File

@ -1,259 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.util.Date;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.Strings;
/**
* UTC time object.
*/
public class ASN1UTCTime
extends ASN1Primitive
{
private byte[] time;
/**
* return an UTC Time from the passed in object.
*
* @exception IllegalArgumentException if the object cannot be converted.
*/
public static ASN1UTCTime getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1UTCTime)
{
return (ASN1UTCTime)obj;
}
if (obj instanceof ASN1UTCTime)
{
return new ASN1UTCTime(((ASN1UTCTime)obj).time);
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return an UTC Time from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
*/
public static ASN1UTCTime getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Object o = obj.getObject();
if (explicit || o instanceof ASN1UTCTime)
{
return getInstance(o);
}
else
{
return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
}
}
/**
* The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
* never encoded. When you're creating one of these objects from scratch, that's
* what you want to use, otherwise we'll try to deal with whatever gets read from
* the input stream... (this is why the input format is different from the getTime()
* method output).
* <p>
*
* @param time the time string.
*/
public ASN1UTCTime(
String time)
{
if (time.charAt(time.length() - 1) != 'Z')
{
// we accept this as a variation
if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
{
throw new IllegalArgumentException("time needs to be in format YYMMDDHHMMSSZ");
}
}
this.time = Strings.toByteArray(time);
}
/**
* base constructor from a java.util.date object
*/
public ASN1UTCTime(
Date time)
{
this.time = Strings.toByteArray(DateFormatter.toUTCDateString(time));
}
ASN1UTCTime(
byte[] time)
{
this.time = time;
}
/**
* return the time as a date based on whatever a 2 digit year will return. For
* standardised processing use getAdjustedDate().
*
* @return the resulting date
*/
public Date getDate()
{
return DateFormatter.adjustedFromUTCDateString(time);
}
/**
* return the time as an adjusted date
* in the range of 1950 - 2049.
*
* @return a date in the range of 1950 to 2049.
*/
public Date getAdjustedDate()
{
return DateFormatter.adjustedFromUTCDateString(time);
}
/**
* return the time - always in the form of
* YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
* </pre>
* To read in the time and get a date which is compatible with our local
* time zone.
* <p>
* <b>Note:</b> In some cases, due to the local date processing, this
* may lead to unexpected results. If you want to stick the normal
* convention of 1950 to 2049 use the getAdjustedTime() method.
*/
public String getTime()
{
String stime = Strings.fromByteArray(time);
//
// standardise the format.
//
if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
{
if (stime.length() == 11)
{
return stime.substring(0, 10) + "00GMT+00:00";
}
else
{
return stime.substring(0, 12) + "GMT+00:00";
}
}
else
{
int index = stime.indexOf('-');
if (index < 0)
{
index = stime.indexOf('+');
}
String d = stime;
if (index == stime.length() - 3)
{
d += "00";
}
if (index == 10)
{
return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
}
else
{
return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
}
}
}
/**
* return a time string as an adjusted date with a 4 digit year. This goes
* in the range of 1950 - 2049.
*/
public String getAdjustedTime()
{
String d = this.getTime();
if (d.charAt(0) < '5')
{
return "20" + d;
}
else
{
return "19" + d;
}
}
/**
* Return the time.
* @return The time string as it appeared in the encoded object.
*/
public String getTimeString()
{
return Strings.fromByteArray(time);
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
int length = time.length;
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.UTC_TIME);
int length = time.length;
out.writeLength(length);
for (int i = 0; i != length; i++)
{
out.write((byte)time[i]);
}
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1UTCTime))
{
return false;
}
return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
}
public int hashCode()
{
return Arrays.hashCode(time);
}
public String toString()
{
return Strings.fromByteArray(time);
}
}

View File

@ -1,31 +0,0 @@
package org.spongycastle.asn1;
class DERFactory
{
static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
static final ASN1Set EMPTY_SET = new DERSet();
static ASN1Sequence createSequence(ASN1EncodableVector v)
{
if (v.size() < 1)
{
return EMPTY_SEQUENCE;
}
else
{
return new DLSequence(v);
}
}
static ASN1Set createSet(ASN1EncodableVector v)
{
if (v.size() < 1)
{
return EMPTY_SET;
}
else
{
return new DLSet(v);
}
}
}

View File

@ -1,27 +0,0 @@
package org.spongycastle.asn1;
import java.util.Date;
public class DERGeneralizedTime
extends ASN1GeneralizedTime
{
DERGeneralizedTime(byte[] bytes)
{
super(bytes);
}
public DERGeneralizedTime(Date date)
{
super(date);
}
public DERGeneralizedTime(Date date, boolean includeMillis)
{
super(date, includeMillis);
}
public DERGeneralizedTime(String time)
{
super(time);
}
}

View File

@ -1,22 +0,0 @@
package org.spongycastle.asn1;
import java.util.Date;
public class DERUTCTime
extends ASN1UTCTime
{
DERUTCTime(byte[] bytes)
{
super(bytes);
}
public DERUTCTime(Date date)
{
super(date);
}
public DERUTCTime(String time)
{
super(time);
}
}

View File

@ -1,272 +0,0 @@
package org.spongycastle.asn1;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
class DateFormatter
{
// YYMMDDHHMMSSZ
static String toUTCDateString(Date date)
{
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.setTime(date);
return format2Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND)) + "Z";
}
static Date adjustedFromUTCDateString(byte[] date)
{
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
int year = toInt2(date, 0);
if (year < 50)
{
year += 2000;
}
else
{
year += 1900;
}
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, toInt2(date, 2) - 1);
calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 4));
calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 6));
calendar.set(Calendar.MINUTE, toInt2(date, 8));
int tzChar = 10;
if (isNumber(date, tzChar))
{
calendar.set(Calendar.SECOND, toInt2(date, 10));
tzChar = 12;
}
else
{
calendar.set(Calendar.SECOND, 0);
}
calendar.set(Calendar.MILLISECOND, 0);
if (date[tzChar] != 'Z')
{
int hoursOff = 0;
int minutesOff = 0;
hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
if (date.length > tzChar + 3)
{
minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
}
if (date[tzChar] == '-')
{
return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
}
else
{
return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
}
}
return calendar.getTime();
}
static String getGeneralizedTimeDateString(Date date, boolean includeMillis)
{
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.setTime(date);
String time = format4Year(calendar.get(Calendar.YEAR)) + format2(calendar.get(Calendar.MONTH) + 1) + format2(calendar.get(Calendar.DAY_OF_MONTH))
+ format2(calendar.get(Calendar.HOUR_OF_DAY)) + format2(calendar.get(Calendar.MINUTE)) + format2(calendar.get(Calendar.SECOND));
if (includeMillis)
{
time += "." + format3(calendar.get(Calendar.MILLISECOND));
}
return time + "Z";
}
static Date fromGeneralizedTimeString(byte[] date)
{
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
int year = toInt4(date, 0);
if (isLocalTime(date))
{
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
}
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, toInt2(date, 4) - 1);
calendar.set(Calendar.DAY_OF_MONTH, toInt2(date, 6));
calendar.set(Calendar.HOUR_OF_DAY, toInt2(date, 8));
calendar.set(Calendar.MINUTE, toInt2(date, 10));
int tzChar = 12;
if (isNumber(date, tzChar))
{
calendar.set(Calendar.SECOND, toInt2(date, 12));
tzChar = 14;
}
else
{
calendar.set(Calendar.SECOND, 0);
}
if (tzChar != date.length && date[tzChar] == '.')
{
int millis = 0;
tzChar++;
if (isNumber(date, tzChar))
{
millis = (date[tzChar] - '0') * 100;
tzChar++;
}
if (tzChar != date.length && isNumber(date, tzChar))
{
millis += (date[tzChar] - '0') * 10;
tzChar++;
}
if (tzChar != date.length && isNumber(date, tzChar))
{
millis += (date[tzChar] - '0');
tzChar++;
}
calendar.set(Calendar.MILLISECOND, millis);
}
else
{
calendar.set(Calendar.MILLISECOND, 0);
}
// skip nano-seconds
while (tzChar != date.length && isNumber(date, tzChar))
{
tzChar++;
}
if (tzChar != date.length && date[tzChar] != 'Z')
{
int hoursOff = 0;
int minutesOff = 0;
hoursOff = toInt2(date, tzChar + 1) * 60 * 60 * 1000;
if (date.length > tzChar + 3)
{
minutesOff = toInt2(date, tzChar + 3) * 60 * 1000;
}
if (date[tzChar] == '-')
{
return new Date(calendar.getTime().getTime() + hoursOff + minutesOff);
}
else
{
return new Date(calendar.getTime().getTime() - (hoursOff + minutesOff));
}
}
return calendar.getTime();
}
private static String format2(int v)
{
if (v < 10)
{
return "0" + v;
}
return Integer.toString(v);
}
private static String format2Year(int v)
{
if (v > 2000)
{
v = v - 2000;
}
else
{
v = v - 1900;
}
return format2(v);
}
private static String format3(int v)
{
if (v < 10)
{
return "00" + v;
}
if (v < 100)
{
return "0" + v;
}
return Integer.toString(v);
}
private static String format4Year(int v)
{
if (v < 10)
{
return "000" + v;
}
if (v < 100)
{
return "00" + v;
}
if (v < 1000)
{
return "0" + v;
}
return Integer.toString(v);
}
private static boolean isNumber(byte[] input, int off)
{
byte b = input[off];
return (b >= '0') && (b <= '9');
}
private static boolean isLocalTime(byte[] date)
{
for (int i = date.length - 1; i > date.length - 6; i--)
{
if (date[i] == 'Z' || date[i] == '-' || date[i] == '+')
{
return false;
}
}
return true;
}
private static int toInt2(byte[] input, int off)
{
return (input[off] - '0') * 10 + (input[off + 1] - '0');
}
private static int toInt4(byte[] input, int off)
{
return toInt2(input, off) * 100 + toInt2(input, off + 2) ;
}
}

View File

@ -1,88 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
class StreamUtil
{
/**
* Find out possible longest length...
*
* @param in input stream of interest
* @return length calculation or MAX_VALUE.
*/
static int findLimit(InputStream in)
{
if (in instanceof LimitedInputStream)
{
return ((LimitedInputStream)in).getRemaining();
}
else if (in instanceof ASN1InputStream)
{
return ((ASN1InputStream)in).getLimit();
}
else if (in instanceof ByteArrayInputStream)
{
return ((ByteArrayInputStream)in).available();
}
return Integer.MAX_VALUE;
}
static int calculateBodyLength(
int length)
{
int count = 1;
if (length > 127)
{
int size = 1;
int val = length;
while ((val >>>= 8) != 0)
{
size++;
}
for (int i = (size - 1) * 8; i >= 0; i -= 8)
{
count++;
}
}
return count;
}
static int calculateTagLength(int tagNo)
throws IOException
{
int length = 1;
if (tagNo >= 31)
{
if (tagNo < 128)
{
length++;
}
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);
length += stack.length - pos;
}
}
return length;
}
}

View File

@ -1,122 +0,0 @@
package org.spongycastle.asn1.cms;
import java.util.Calendar;
import java.util.Date;
import org.spongycastle.asn1.ASN1Choice;
import org.spongycastle.asn1.ASN1Object;
import org.spongycastle.asn1.ASN1Primitive;
import org.spongycastle.asn1.ASN1TaggedObject;
import org.spongycastle.asn1.ASN1GeneralizedTime;
import org.spongycastle.asn1.ASN1UTCTime;
public class Time
extends ASN1Object
implements ASN1Choice
{
ASN1Primitive time;
public static Time getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
return getInstance(obj.getObject()); // must be explicitly tagged
}
public Time(
ASN1Primitive time)
{
if (!(time instanceof ASN1UTCTime)
&& !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
this.time = time;
}
/**
* creates a time object from a given date - if the date is between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
*/
public Time(
Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
if (year < 1950 || year > 2049)
{
time = new ASN1GeneralizedTime(date);
}
else
{
time = new ASN1UTCTime(date);
}
}
public static Time getInstance(
Object obj)
{
if (obj == null || obj instanceof Time)
{
return (Time)obj;
}
else if (obj instanceof ASN1UTCTime)
{
return new Time((ASN1UTCTime)obj);
}
else if (obj instanceof ASN1GeneralizedTime)
{
return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
public String getTime()
{
if (time instanceof ASN1UTCTime)
{
return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
return ((ASN1GeneralizedTime)time).getTime();
}
}
public Date getDate()
{
if (time instanceof ASN1UTCTime)
{
return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
return ((ASN1GeneralizedTime)time).getDate();
}
}
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*/
public ASN1Primitive toASN1Primitive()
{
return time;
}
public String toString()
{
return getTime();
}
}

View File

@ -1,70 +0,0 @@
package org.spongycastle.asn1.eac;
import org.spongycastle.util.Arrays;
/**
* EAC encoding date object
*/
public class PackedDate
{
private byte[] time;
public PackedDate(
String time)
{
this.time = convert(time);
}
private byte[] convert(String sTime)
{
char[] digs = sTime.toCharArray();
byte[] date = new byte[6];
for (int i = 0; i != 6; i++)
{
date[i] = (byte)(digs[i] - '0');
}
return date;
}
PackedDate(
byte[] bytes)
{
this.time = bytes;
}
public int hashCode()
{
return Arrays.hashCode(time);
}
public boolean equals(Object o)
{
if (!(o instanceof PackedDate))
{
return false;
}
PackedDate other = (PackedDate)o;
return Arrays.areEqual(time, other.time);
}
public String toString()
{
char[] dateC = new char[time.length];
for (int i = 0; i != dateC.length; i++)
{
dateC[i] = (char)((time[i] & 0xff) + '0');
}
return new String(dateC);
}
public byte[] getEncoding()
{
return time;
}
}

View File

@ -1,122 +0,0 @@
package org.spongycastle.asn1.x509;
import java.util.Calendar;
import java.util.Date;
import org.spongycastle.asn1.ASN1Choice;
import org.spongycastle.asn1.ASN1Object;
import org.spongycastle.asn1.ASN1Primitive;
import org.spongycastle.asn1.ASN1TaggedObject;
import org.spongycastle.asn1.ASN1GeneralizedTime;
import org.spongycastle.asn1.ASN1UTCTime;
public class Time
extends ASN1Object
implements ASN1Choice
{
ASN1Primitive time;
public static Time getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
return getInstance(obj.getObject()); // must be explicitly tagged
}
public Time(
ASN1Primitive time)
{
if (!(time instanceof ASN1UTCTime)
&& !(time instanceof ASN1GeneralizedTime))
{
throw new IllegalArgumentException("unknown object passed to Time");
}
this.time = time;
}
/**
* creates a time object from a given date - if the date is between 1950
* and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
* is used.
*/
public Time(
Date date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
if (year < 1950 || year > 2049)
{
time = new ASN1GeneralizedTime(date);
}
else
{
time = new ASN1UTCTime(date);
}
}
public static Time getInstance(
Object obj)
{
if (obj == null || obj instanceof Time)
{
return (Time)obj;
}
else if (obj instanceof ASN1UTCTime)
{
return new Time((ASN1UTCTime)obj);
}
else if (obj instanceof ASN1GeneralizedTime)
{
return new Time((ASN1GeneralizedTime)obj);
}
throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
}
public String getTime()
{
if (time instanceof ASN1UTCTime)
{
return ((ASN1UTCTime)time).getAdjustedTime();
}
else
{
return ((ASN1GeneralizedTime)time).getTime();
}
}
public Date getDate()
{
if (time instanceof ASN1UTCTime)
{
return ((ASN1UTCTime)time).getAdjustedDate();
}
else
{
return ((ASN1GeneralizedTime)time).getDate();
}
}
/**
* Produce an object suitable for an ASN1OutputStream.
* <pre>
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
*/
public ASN1Primitive toASN1Primitive()
{
return time;
}
public String toString()
{
return getTime();
}
}

View File

@ -1,410 +0,0 @@
package org.spongycastle.crypto.encodings;
import java.security.SecureRandom;
import org.spongycastle.crypto.AsymmetricBlockCipher;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.InvalidCipherTextException;
import org.spongycastle.crypto.params.AsymmetricKeyParameter;
import org.spongycastle.crypto.params.ParametersWithRandom;
/**
* this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
* depends on your application - see PKCS1 Version 2 for details.
*/
public class PKCS1Encoding
implements AsymmetricBlockCipher
{
/**
* some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
* work with one of these set the system property org.spongycastle.pkcs1.strict to false.
* <p>
* The system property is checked during construction of the encoding object, it is set to
* true by default.
* </p>
*/
public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.spongycastle.pkcs1.strict";
private static final int HEADER_LENGTH = 10;
private SecureRandom random;
private AsymmetricBlockCipher engine;
private boolean forEncryption;
private boolean forPrivateKey;
private boolean useStrictLength;
private int pLen = -1;
private byte[] fallback = null;
/**
* Basic constructor.
* @param cipher
*/
public PKCS1Encoding(
AsymmetricBlockCipher cipher)
{
this.engine = cipher;
this.useStrictLength = useStrict();
}
/**
* Constructor for decryption with a fixed plaintext length.
*
* @param cipher The cipher to use for cryptographic operation.
* @param pLen Length of the expected plaintext.
*/
public PKCS1Encoding(
AsymmetricBlockCipher cipher,
int pLen)
{
this.engine = cipher;
this.useStrictLength = useStrict();
this.pLen = pLen;
}
/**
* Constructor for decryption with a fixed plaintext length and a fallback
* value that is returned, if the padding is incorrect.
*
* @param cipher
* The cipher to use for cryptographic operation.
* @param fallback
* The fallback value, we don't to a arraycopy here.
*/
public PKCS1Encoding(
AsymmetricBlockCipher cipher,
byte[] fallback)
{
this.engine = cipher;
this.useStrictLength = useStrict();
this.fallback = fallback;
this.pLen = fallback.length;
}
//
// for J2ME compatibility
//
private boolean useStrict()
{
// required if security manager has been installed.
String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
return strict == null || strict.equals("true");
}
public AsymmetricBlockCipher getUnderlyingCipher()
{
return engine;
}
public void init(
boolean forEncryption,
CipherParameters param)
{
AsymmetricKeyParameter kParam;
if (param instanceof ParametersWithRandom)
{
ParametersWithRandom rParam = (ParametersWithRandom)param;
this.random = rParam.getRandom();
kParam = (AsymmetricKeyParameter)rParam.getParameters();
}
else
{
this.random = new SecureRandom();
kParam = (AsymmetricKeyParameter)param;
}
engine.init(forEncryption, param);
this.forPrivateKey = kParam.isPrivate();
this.forEncryption = forEncryption;
}
public int getInputBlockSize()
{
int baseBlockSize = engine.getInputBlockSize();
if (forEncryption)
{
return baseBlockSize - HEADER_LENGTH;
}
else
{
return baseBlockSize;
}
}
public int getOutputBlockSize()
{
int baseBlockSize = engine.getOutputBlockSize();
if (forEncryption)
{
return baseBlockSize;
}
else
{
return baseBlockSize - HEADER_LENGTH;
}
}
public byte[] processBlock(
byte[] in,
int inOff,
int inLen)
throws InvalidCipherTextException
{
if (forEncryption)
{
return encodeBlock(in, inOff, inLen);
}
else
{
return decodeBlock(in, inOff, inLen);
}
}
private byte[] encodeBlock(
byte[] in,
int inOff,
int inLen)
throws InvalidCipherTextException
{
if (inLen > getInputBlockSize())
{
throw new IllegalArgumentException("input data too large");
}
byte[] block = new byte[engine.getInputBlockSize()];
if (forPrivateKey)
{
block[0] = 0x01; // type code 1
for (int i = 1; i != block.length - inLen - 1; i++)
{
block[i] = (byte)0xFF;
}
}
else
{
random.nextBytes(block); // random fill
block[0] = 0x02; // type code 2
//
// a zero byte marks the end of the padding, so all
// the pad bytes must be non-zero.
//
for (int i = 1; i != block.length - inLen - 1; i++)
{
while (block[i] == 0)
{
block[i] = (byte)random.nextInt();
}
}
}
block[block.length - inLen - 1] = 0x00; // mark the end of the padding
System.arraycopy(in, inOff, block, block.length - inLen, inLen);
return engine.processBlock(block, 0, block.length);
}
/**
* Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
* for encryption.
*
* @param encoded The Plaintext.
* @param pLen Expected length of the plaintext.
* @return Either 0, if the encoding is correct, or -1, if it is incorrect.
*/
private static int checkPkcs1Encoding(byte[] encoded, int pLen) {
int correct = 0;
/*
* Check if the first two bytes are 0 2
*/
correct |= (encoded[0] ^ 2);
/*
* Now the padding check, check for no 0 byte in the padding
*/
int plen = encoded.length - (
pLen /* Lenght of the PMS */
+ 1 /* Final 0-byte before PMS */
);
for (int i = 1; i < plen; i++) {
int tmp = encoded[i];
tmp |= tmp >> 1;
tmp |= tmp >> 2;
tmp |= tmp >> 4;
correct |= (tmp & 1) - 1;
}
/*
* Make sure the padding ends with a 0 byte.
*/
correct |= encoded[encoded.length - (pLen +1)];
/*
* Return 0 or 1, depending on the result.
*/
correct |= correct >> 1;
correct |= correct >> 2;
correct |= correct >> 4;
return ~((correct & 1) - 1);
}
/**
* Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
*
* @param in The encrypted block.
* @param inOff Offset in the encrypted block.
* @param inLen Length of the encrypted block.
* //@param pLen Length of the desired output.
* @return The plaintext without padding, or a random value if the padding was incorrect.
*
* @throws InvalidCipherTextException
*/
private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen)
throws InvalidCipherTextException
{
if (!forPrivateKey)
{
throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
}
byte[] block = engine.processBlock(in, inOff, inLen);
byte[] random = null;
if (this.fallback == null)
{
random = new byte[this.pLen];
this.random.nextBytes(random);
}
else
{
random = fallback;
}
/*
* TODO: This is a potential dangerous side channel. However, you can
* fix this by changing the RSA engine in a way, that it will always
* return blocks of the same length and prepend them with 0 bytes if
* needed.
*/
if (block.length < getOutputBlockSize())
{
throw new InvalidCipherTextException("block truncated");
}
/*
* TODO: Potential side channel. Fix it by making the engine always
* return blocks of the correct length.
*/
if (useStrictLength && block.length != engine.getOutputBlockSize())
{
throw new InvalidCipherTextException("block incorrect size");
}
/*
* Check the padding.
*/
int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen);
/*
* Now, to a constant time constant memory copy of the decrypted value
* or the random value, depending on the validity of the padding.
*/
byte[] result = new byte[this.pLen];
for (int i = 0; i < this.pLen; i++)
{
result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct));
}
return result;
}
/**
* @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
*/
private byte[] decodeBlock(
byte[] in,
int inOff,
int inLen)
throws InvalidCipherTextException
{
/*
* If the length of the expected plaintext is known, we use a constant-time decryption.
* If the decryption fails, we return a random value.
*/
if (this.pLen != -1) {
return this.decodeBlockOrRandom(in, inOff, inLen);
}
byte[] block = engine.processBlock(in, inOff, inLen);
if (block.length < getOutputBlockSize())
{
throw new InvalidCipherTextException("block truncated");
}
byte type = block[0];
if (forPrivateKey)
{
if (type != 2)
{
throw new InvalidCipherTextException("unknown block type");
}
}
else
{
if (type != 1)
{
throw new InvalidCipherTextException("unknown block type");
}
}
if (useStrictLength && block.length != engine.getOutputBlockSize())
{
throw new InvalidCipherTextException("block incorrect size");
}
//
// find and extract the message block.
//
int start;
for (start = 1; start != block.length; start++)
{
byte pad = block[start];
if (pad == 0)
{
break;
}
if (type == 1 && pad != (byte)0xff)
{
throw new InvalidCipherTextException("block padding incorrect");
}
}
start++; // data should start at the next byte
if (start > block.length || start < HEADER_LENGTH)
{
throw new InvalidCipherTextException("no data in block");
}
byte[] result = new byte[block.length - start];
System.arraycopy(block, start, result, 0, result.length);
return result;
}
}

View File

@ -1,177 +0,0 @@
package org.spongycastle.crypto.examples;
import java.io.*;
import java.lang.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;
import org.spongycastle.util.test.*;
import org.spongycastle.util.encoders.*;
import org.spongycastle.crypto.*;
import org.spongycastle.crypto.paddings.*;
import org.spongycastle.crypto.engines.*;
import org.spongycastle.crypto.modes.*;
import org.spongycastle.crypto.params.*;
/**
* MIDP is a simple graphics application for the J2ME CLDC/MIDP.
*
* It has hardcoded values for the key and plain text. It also performs the
* standard testing for the chosen cipher, and displays the results.
*
* This example shows how to use the light-weight API and a symmetric cipher.
*
*/
public class MIDPTest extends MIDlet
{
private Display d = null;
private boolean doneEncrypt = false;
private String key = "0123456789abcdef0123456789abcdef";
private String plainText = "www.bouncycastle.org";
private byte[] keyBytes = null;
private byte[] cipherText = null;
private BufferedBlockCipher cipher = null;
private String[] cipherNames = {"DES", "DESede", "IDEA", "Rijndael", "Twofish"};
private Form output = null;
public void startApp()
{
Display.getDisplay(this).setCurrent(output);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
public MIDPTest()
{
output = new Form("BouncyCastle");
output.append("Key: " + key.substring(0, 7) + "...\n");
output.append("In : " + plainText.substring(0, 7) + "...\n");
cipherText = performEncrypt(Hex.decode(key.getBytes()), plainText);
String ctS = new String(Hex.encode(cipherText));
output.append("\nCT : " + ctS.substring(0, 7) + "...\n");
String decryptText = performDecrypt(Hex.decode(key.getBytes()), cipherText);
output.append("PT : " + decryptText.substring(0, 7) + "...\n");
if (decryptText.compareTo(plainText) == 0)
{
output.append("Success");
}
else
{
output.append("Failure");
message("[" + plainText + "]");
message("[" + decryptText + "]");
}
}
private byte[] performEncrypt(byte[] key, String plainText)
{
byte[] ptBytes = plainText.getBytes();
cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(getEngineInstance()));
String name = cipher.getUnderlyingCipher().getAlgorithmName();
message("Using " + name);
cipher.init(true, new KeyParameter(key));
byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)];
int oLen = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0);
try
{
cipher.doFinal(rv, oLen);
}
catch (CryptoException ce)
{
message("Ooops, encrypt exception");
status(ce.toString());
}
return rv;
}
private String performDecrypt(byte[] key, byte[] cipherText)
{
cipher.init(false, new KeyParameter(key));
byte[] rv = new byte[cipher.getOutputSize(cipherText.length)];
int oLen = cipher.processBytes(cipherText, 0, cipherText.length, rv, 0);
try
{
cipher.doFinal(rv, oLen);
}
catch (CryptoException ce)
{
message("Ooops, decrypt exception");
status(ce.toString());
}
return new String(rv).trim();
}
private int whichCipher()
{
return 4; // DES
}
private BlockCipher getEngineInstance()
{
// returns a block cipher according to the current
// state of the radio button lists. This is only
// done prior to encryption.
BlockCipher rv = null;
switch (whichCipher())
{
case 0 :
rv = new DESEngine();
break;
case 1 :
rv = new DESedeEngine();
break;
case 2 :
rv = new IDEAEngine();
break;
case 3 :
rv = new RijndaelEngine();
break;
case 4 :
rv = new TwofishEngine();
break;
default :
rv = new DESEngine();
break;
}
return rv;
}
public void message(String s)
{
System.out.println("M:" + s);
}
public void status(String s)
{
System.out.println("S:" + s);
}
}

View File

@ -1,6 +0,0 @@
MIDlet-1: MIDPTest, , org.spongycastle.crypto.examples.MIDPTest
MIDlet-Name: MIDPTest
MIDlet-Jar-Size: 300000
MIDlet-Jar-URL: midp_test.jar
MIDlet-Vendor: The Legion of the Bouncy Castle
MIDlet-Version: 1.0.0

View File

@ -1,7 +0,0 @@
MIDlet-1: MIDPTTest, , org.spongycastle.crypto.examples.MIDPTest
MIDlet-Name: MIDPTest
MIDlet-Version: 1.0.0
MIDlet-Vendor: Jon Eaves
Created-By: 1.3.1 (Sun Microsystems Inc.)
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-1.0

View File

@ -1,258 +0,0 @@
package org.spongycastle.crypto.params;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.digests.SkeinDigest;
import org.spongycastle.crypto.digests.SkeinEngine;
import org.spongycastle.crypto.macs.SkeinMac;
import org.spongycastle.util.Integers;
/**
* Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
* <p/>
* Parameterised Skein can be used for:
* <ul>
* <li>MAC generation, by providing a {@link SkeinParameters.Builder#setKey(byte[]) key}.</li>
* <li>Randomised hashing, by providing a {@link SkeinParameters.Builder#setNonce(byte[]) nonce}.</li>
* <li>A hash function for digital signatures, associating a
* {@link SkeinParameters.Builder#setPublicKey(byte[]) public key} with the message digest.</li>
* <li>A key derivation function, by providing a
* {@link SkeinParameters.Builder#setKeyIdentifier(byte[]) key identifier}.</li>
* <li>Personalised hashing, by providing a
* {@link SkeinParameters.Builder#setPersonalisation(Date, String, String) recommended format} or
* {@link SkeinParameters.Builder#setPersonalisation(byte[]) arbitrary} personalisation string.</li>
* </ul>
*
* @see SkeinEngine
* @see SkeinDigest
* @see SkeinMac
*/
public class SkeinParameters
implements CipherParameters
{
/**
* The parameter type for a secret key, supporting MAC or KDF functions: {@value
* #PARAM_TYPE_KEY}.
*/
public static final int PARAM_TYPE_KEY = 0;
/**
* The parameter type for the Skein configuration block: {@value #PARAM_TYPE_CONFIG}.
*/
public static final int PARAM_TYPE_CONFIG = 4;
/**
* The parameter type for a personalisation string: {@value #PARAM_TYPE_PERSONALISATION}.
*/
public static final int PARAM_TYPE_PERSONALISATION = 8;
/**
* The parameter type for a public key: {@value #PARAM_TYPE_PUBLIC_KEY}.
*/
public static final int PARAM_TYPE_PUBLIC_KEY = 12;
/**
* The parameter type for a key identifier string: {@value #PARAM_TYPE_KEY_IDENTIFIER}.
*/
public static final int PARAM_TYPE_KEY_IDENTIFIER = 16;
/**
* The parameter type for a nonce: {@value #PARAM_TYPE_NONCE}.
*/
public static final int PARAM_TYPE_NONCE = 20;
/**
* The parameter type for the message: {@value #PARAM_TYPE_MESSAGE}.
*/
public static final int PARAM_TYPE_MESSAGE = 48;
/**
* The parameter type for the output transformation: {@value #PARAM_TYPE_OUTPUT}.
*/
public static final int PARAM_TYPE_OUTPUT = 63;
private Hashtable parameters;
public SkeinParameters()
{
this(new Hashtable());
}
private SkeinParameters(final Hashtable parameters)
{
this.parameters = parameters;
}
/**
* Obtains a map of type (Integer) to value (byte[]) for the parameters tracked in this object.
*/
public Hashtable getParameters()
{
return parameters;
}
/**
* Obtains the value of the {@link #PARAM_TYPE_KEY key parameter}, or <code>null</code> if not
* set.
*/
public byte[] getKey()
{
return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY));
}
/**
* Obtains the value of the {@link #PARAM_TYPE_PERSONALISATION personalisation parameter}, or
* <code>null</code> if not set.
*/
public byte[] getPersonalisation()
{
return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PERSONALISATION));
}
/**
* Obtains the value of the {@link #PARAM_TYPE_PUBLIC_KEY public key parameter}, or
* <code>null</code> if not set.
*/
public byte[] getPublicKey()
{
return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PUBLIC_KEY));
}
/**
* Obtains the value of the {@link #PARAM_TYPE_KEY_IDENTIFIER key identifier parameter}, or
* <code>null</code> if not set.
*/
public byte[] getKeyIdentifier()
{
return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY_IDENTIFIER));
}
/**
* Obtains the value of the {@link #PARAM_TYPE_NONCE nonce parameter}, or <code>null</code> if
* not set.
*/
public byte[] getNonce()
{
return (byte[])parameters.get(Integers.valueOf(PARAM_TYPE_NONCE));
}
/**
* A builder for {@link SkeinParameters}.
*/
public static class Builder
{
private Hashtable parameters = new Hashtable();
public Builder()
{
}
public Builder(Hashtable paramsMap)
{
Enumeration keys = paramsMap.keys();
while (keys.hasMoreElements())
{
Integer key = (Integer)keys.nextElement();
parameters.put(key, paramsMap.get(key));
}
}
public Builder(SkeinParameters params)
{
Enumeration keys = params.parameters.keys();
while (keys.hasMoreElements())
{
Integer key = (Integer)keys.nextElement();
parameters.put(key, params.parameters.get(key));
}
}
/**
* Sets a parameters to apply to the Skein hash function.<br>
* Parameter types must be in the range 0,5..62, and cannot use the value {@value
* SkeinParameters#PARAM_TYPE_MESSAGE} (reserved for message body).
* <p/>
* Parameters with type < {@value SkeinParameters#PARAM_TYPE_MESSAGE} are processed before
* the message content, parameters with type > {@value SkeinParameters#PARAM_TYPE_MESSAGE}
* are processed after the message and prior to output.
*
* @param type the type of the parameter, in the range 5..62.
* @param value the byte sequence of the parameter.
* @return
*/
public Builder set(int type, byte[] value)
{
if (value == null)
{
throw new IllegalArgumentException("Parameter value must not be null.");
}
if ((type != PARAM_TYPE_KEY)
&& (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE))
{
throw new IllegalArgumentException("Parameter types must be in the range 0,5..47,49..62.");
}
if (type == PARAM_TYPE_CONFIG)
{
throw new IllegalArgumentException("Parameter type " + PARAM_TYPE_CONFIG
+ " is reserved for internal use.");
}
this.parameters.put(Integers.valueOf(type), value);
return this;
}
/**
* Sets the {@link SkeinParameters#PARAM_TYPE_KEY} parameter.
*/
public Builder setKey(byte[] key)
{
return set(PARAM_TYPE_KEY, key);
}
/**
* Sets the {@link SkeinParameters#PARAM_TYPE_PERSONALISATION} parameter.
*/
public Builder setPersonalisation(byte[] personalisation)
{
return set(PARAM_TYPE_PERSONALISATION, personalisation);
}
/**
* Sets the {@link SkeinParameters#PARAM_TYPE_KEY_IDENTIFIER} parameter.
*/
public Builder setPublicKey(byte[] publicKey)
{
return set(PARAM_TYPE_PUBLIC_KEY, publicKey);
}
/**
* Sets the {@link SkeinParameters#PARAM_TYPE_KEY_IDENTIFIER} parameter.
*/
public Builder setKeyIdentifier(byte[] keyIdentifier)
{
return set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier);
}
/**
* Sets the {@link SkeinParameters#PARAM_TYPE_NONCE} parameter.
*/
public Builder setNonce(byte[] nonce)
{
return set(PARAM_TYPE_NONCE, nonce);
}
/**
* Constructs a new {@link SkeinParameters} instance with the parameters provided to this
* builder.
*/
public SkeinParameters build()
{
return new SkeinParameters(parameters);
}
}
}

View File

@ -1,131 +0,0 @@
package org.spongycastle.crypto.tls;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import org.spongycastle.asn1.ASN1Encoding;
import org.spongycastle.asn1.ocsp.ResponderID;
import org.spongycastle.asn1.x509.Extensions;
/**
* RFC 3546 3.6
*/
public class OCSPStatusRequest
{
protected Vector responderIDList;
protected Extensions requestExtensions;
/**
* @param responderIDList
* a {@link Vector} of {@link ResponderID}, specifying the list of trusted OCSP
* responders. An empty list has the special meaning that the responders are
* implicitly known to the server - e.g., by prior arrangement.
* @param requestExtensions
* OCSP request extensions. A null value means that there are no extensions.
*/
public OCSPStatusRequest(Vector responderIDList, Extensions requestExtensions)
{
this.responderIDList = responderIDList;
this.requestExtensions = requestExtensions;
}
/**
* @return a {@link Vector} of {@link ResponderID}
*/
public Vector getResponderIDList()
{
return responderIDList;
}
/**
* @return OCSP request extensions
*/
public Extensions getRequestExtensions()
{
return requestExtensions;
}
/**
* Encode this {@link OCSPStatusRequest} to an {@link OutputStream}.
*
* @param output
* the {@link OutputStream} to encode to.
* @throws IOException
*/
public void encode(OutputStream output) throws IOException
{
if (responderIDList == null || responderIDList.isEmpty())
{
TlsUtils.writeUint16(0, output);
}
else
{
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for (int i = 0; i < responderIDList.size(); ++i)
{
ResponderID responderID = (ResponderID) responderIDList.elementAt(i);
byte[] derEncoding = responderID.getEncoded(ASN1Encoding.DER);
TlsUtils.writeOpaque16(derEncoding, buf);
}
TlsUtils.checkUint16(buf.size());
TlsUtils.writeUint16(buf.size(), output);
output.write(buf.toByteArray());
}
if (requestExtensions == null)
{
TlsUtils.writeUint16(0, output);
}
else
{
byte[] derEncoding = requestExtensions.getEncoded(ASN1Encoding.DER);
TlsUtils.checkUint16(derEncoding.length);
TlsUtils.writeUint16(derEncoding.length, output);
output.write(derEncoding);
}
}
/**
* Parse an {@link OCSPStatusRequest} from an {@link InputStream}.
*
* @param input
* the {@link InputStream} to parse from.
* @return an {@link OCSPStatusRequest} object.
* @throws IOException
*/
public static OCSPStatusRequest parse(InputStream input) throws IOException
{
Vector responderIDList = new Vector();
{
int length = TlsUtils.readUint16(input);
if (length > 0)
{
byte[] data = TlsUtils.readFully(length, input);
ByteArrayInputStream buf = new ByteArrayInputStream(data);
do
{
byte[] derEncoding = TlsUtils.readOpaque16(buf);
ResponderID responderID = ResponderID.getInstance(TlsUtils.readDERObject(derEncoding));
responderIDList.addElement(responderID);
}
while (buf.available() > 0);
}
}
Extensions requestExtensions = null;
{
int length = TlsUtils.readUint16(input);
if (length > 0)
{
byte[] derEncoding = TlsUtils.readFully(length, input);
requestExtensions = Extensions.getInstance(TlsUtils.readDERObject(derEncoding));
}
}
return new OCSPStatusRequest(responderIDList, requestExtensions);
}
}

View File

@ -1,86 +0,0 @@
package org.spongycastle.crypto.tls;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
public class ServerNameList
{
protected Vector serverNameList;
/**
* @param serverNameList a {@link Vector} of {@link ServerName}.
*/
public ServerNameList(Vector serverNameList)
{
if (serverNameList == null || serverNameList.isEmpty())
{
throw new IllegalArgumentException("'serverNameList' must not be null or empty");
}
this.serverNameList = serverNameList;
}
/**
* @return a {@link Vector} of {@link ServerName}.
*/
public Vector getServerNameList()
{
return serverNameList;
}
/**
* Encode this {@link ServerNameList} to an {@link OutputStream}.
*
* @param output
* the {@link OutputStream} to encode to.
* @throws IOException
*/
public void encode(OutputStream output) throws IOException
{
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for (int i = 0; i < serverNameList.size(); ++i)
{
ServerName entry = (ServerName)serverNameList.elementAt(i);
entry.encode(buf);
}
TlsUtils.checkUint16(buf.size());
TlsUtils.writeUint16(buf.size(), output);
output.write(buf.toByteArray());
}
/**
* Parse a {@link ServerNameList} from an {@link InputStream}.
*
* @param input
* the {@link InputStream} to parse from.
* @return a {@link ServerNameList} object.
* @throws IOException
*/
public static ServerNameList parse(InputStream input) throws IOException
{
int length = TlsUtils.readUint16(input);
if (length < 1)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
byte[] data = TlsUtils.readFully(length, input);
ByteArrayInputStream buf = new ByteArrayInputStream(data);
Vector server_name_list = new Vector();
while (buf.available() > 0)
{
ServerName entry = ServerName.parse(buf);
server_name_list.addElement(entry);
}
return new ServerNameList(server_name_list);
}
}

View File

@ -1,107 +0,0 @@
package org.spongycastle.crypto.tls;
import java.io.IOException;
import javax.microedition.io.DatagramConnection;
import javax.microedition.io.Datagram;
public class UDPTransport
implements DatagramTransport
{
protected final static int MIN_IP_OVERHEAD = 20;
protected final static int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64;
protected final static int UDP_OVERHEAD = 8;
protected final DatagramConnection socket;
protected final int receiveLimit, sendLimit;
public UDPTransport(DatagramConnection socket, int mtu)
throws IOException
{
//
// In 1.3 and earlier sockets were bound and connected during creation
//
//if (!socket.isBound() || !socket.isConnected())
//{
// throw new IllegalArgumentException("'socket' must be bound and connected");
//}
this.socket = socket;
// NOTE: As of JDK 1.6, can use NetworkInterface.getMTU
this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD;
this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
}
public int getReceiveLimit()
{
return receiveLimit;
}
public int getSendLimit()
{
// TODO[DTLS] Implement Path-MTU discovery?
return sendLimit;
}
public int receive(byte[] buf, int off, int len, int waitMillis)
throws IOException
{
//socket.setSoTimeout(waitMillis); -- not applicable
if (off == 0)
{
Datagram packet = socket.newDatagram(buf, len);
socket.receive(packet);
return packet.getLength();
}
else
{
byte[] rv = new byte[len];
Datagram packet = socket.newDatagram(rv, len);
socket.receive(packet);
System.arraycopy(rv, 0, buf, off, packet.getLength());
return packet.getLength();
}
}
public void send(byte[] buf, int off, int len)
throws IOException
{
if (len > getSendLimit())
{
/*
* RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU,
* the DTLS implementation SHOULD generate an error, thus avoiding sending a packet
* which will be fragmented."
*/
// TODO Exception
}
if (off == 0)
{
Datagram packet = socket.newDatagram(buf, len);
socket.send(packet);
}
else
{
byte[] data = new byte[len];
System.arraycopy(buf, off, data, 0, len);
Datagram packet = socket.newDatagram(data, len);
socket.send(packet);
}
}
public void close()
throws IOException
{
socket.close();
}
}

View File

@ -1,19 +0,0 @@
package org.spongycastle.util;
public class Integers
{
public static int rotateLeft(int i, int distance)
{
return (i << distance) ^ (i >>> -distance);
}
public static int rotateRight(int i, int distance)
{
return (i >>> distance) ^ (i << -distance);
}
public static Integer valueOf(int value)
{
return new Integer(value);
}
}

View File

@ -1,8 +0,0 @@
package org.spongycastle.util;
public interface Selector
{
boolean match(Object obj);
Object clone();
}

View File

@ -1,9 +0,0 @@
package org.spongycastle.util;
public class Shorts
{
public static Short valueOf(short value)
{
return new Short(value);
}
}

View File

@ -1,11 +0,0 @@
package org.spongycastle.util;
public final class Times
{
private static long NANOS_PER_MILLI = 1000000L;
public static long nanoTime()
{
return NANOS_PER_MILLI * System.currentTimeMillis();
}
}

View File

@ -1,84 +0,0 @@
package org.spongycastle.util.test;
import java.io.PrintStream;
import org.spongycastle.util.Arrays;
public abstract class SimpleTest
implements Test
{
public abstract String getName();
private TestResult success()
{
return SimpleTestResult.successful(this, "Okay");
}
protected void fail(
String message)
{
throw new TestFailedException(SimpleTestResult.failed(this, message));
}
protected void fail(
String message,
Throwable throwable)
{
throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
}
protected void fail(
String message,
Object expected,
Object found)
{
throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
}
protected boolean areEqual(
byte[] a,
byte[] b)
{
return Arrays.areEqual(a, b);
}
public TestResult perform()
{
try
{
performTest();
return success();
}
catch (TestFailedException e)
{
return e.getResult();
}
catch (Exception e)
{
return SimpleTestResult.failed(this, "Exception: " + e, e);
}
}
protected static void runTest(
Test test)
{
runTest(test, System.out);
}
protected static void runTest(
Test test,
PrintStream out)
{
TestResult result = test.perform();
out.println(result.toString());
if (result.getException() != null)
{
result.getException().printStackTrace();
}
}
public abstract void performTest()
throws Exception;
}

View File

@ -1,63 +0,0 @@
package org.spongycastle;
/**
* The Bouncy Castle License
*
* Copyright (c) 2000-2014 The Legion Of The Bouncy Castle Inc. (http://www.bouncycastle.org)
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
public class LICENSE
{
public static String licenseText =
"Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) "
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software "
+ System.getProperty("line.separator")
+ "and associated documentation files (the \"Software\"), to deal in the Software without restriction, "
+ System.getProperty("line.separator")
+ "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, "
+ System.getProperty("line.separator")
+ "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,"
+ System.getProperty("line.separator")
+ "subject to the following conditions:"
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "The above copyright notice and this permission notice shall be included in all copies or substantial"
+ System.getProperty("line.separator")
+ "portions of the Software."
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,"
+ System.getProperty("line.separator")
+ "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR"
+ System.getProperty("line.separator")
+ "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
+ System.getProperty("line.separator")
+ "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR"
+ System.getProperty("line.separator")
+ "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER"
+ System.getProperty("line.separator")
+ "DEALINGS IN THE SOFTWARE.";
public static void main(
String[] args)
{
System.out.println(licenseText);
}
}

View File

@ -1,19 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
/**
* Interface to parse ASN.1 application specific objects.
*/
public interface ASN1ApplicationSpecificParser
extends ASN1Encodable, InMemoryRepresentable
{
/**
* Read the next object in the parser.
*
* @return an ASN1Encodable
* @throws IOException on a parsing or decoding error.
*/
ASN1Encodable readObject()
throws IOException;
}

View File

@ -1,204 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import org.spongycastle.util.Arrays;
/**
* Public facade of ASN.1 Boolean data.
* <p>
* Use following to place a new instance of ASN.1 Boolean in your dataset:
* </p>
* <ul>
* <li> ASN1Boolean.TRUE literal</li>
* <li> ASN1Boolean.FALSE literal</li>
* <li> {@link ASN1Boolean#getInstance(boolean) ASN1Boolean.getInstance(boolean)}</li>
* <li> {@link ASN1Boolean#getInstance(int) ASN1Boolean.getInstance(int)}</li>
* </ul>
* </p>
*/
public class ASN1Boolean
extends ASN1Primitive
{
private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
private static final byte[] FALSE_VALUE = new byte[] { 0 };
private byte[] value;
public static final ASN1Boolean FALSE = new ASN1Boolean(false);
public static final ASN1Boolean TRUE = new ASN1Boolean(true);
/**
* return a boolean from the passed in object.
*
* @param obj an ASN1Boolean or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
* @return an ASN1Boolean instance.
*/
public static ASN1Boolean getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1Boolean)
{
return (ASN1Boolean)obj;
}
if (obj instanceof byte[])
{
byte[] enc = (byte[])obj;
try
{
return (ASN1Boolean)fromByteArray(enc);
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct boolean from byte[]: " + e.getMessage());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return an ASN1Boolean from the passed in boolean.
* @return an ASN1Boolean instance.
*/
public static ASN1Boolean getInstance(
boolean value)
{
return (value ? TRUE : FALSE);
}
/**
* return an ASN1Boolean from the passed in value.
* @return an ASN1Boolean instance.
*/
public static ASN1Boolean getInstance(
int value)
{
return (value != 0 ? TRUE : FALSE);
}
/**
* return a Boolean from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
* @return an ASN1Boolean instance.
*/
public static ASN1Boolean getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1Boolean)
{
return getInstance(o);
}
else
{
return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
}
}
ASN1Boolean(
byte[] value)
{
if (value.length != 1)
{
throw new IllegalArgumentException("byte value should have 1 byte in it");
}
if (value[0] == 0)
{
this.value = FALSE_VALUE;
}
else if ((value[0] & 0xff) == 0xff)
{
this.value = TRUE_VALUE;
}
else
{
this.value = Arrays.clone(value);
}
}
/**
* @deprecated use getInstance(boolean) method.
* @param value true or false.
*/
public ASN1Boolean(
boolean value)
{
this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
}
public boolean isTrue()
{
return (value[0] != 0);
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
return 3;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeEncoded(BERTags.BOOLEAN, value);
}
protected boolean asn1Equals(
ASN1Primitive o)
{
if (o instanceof ASN1Boolean)
{
return (value[0] == ((ASN1Boolean)o).value[0]);
}
return false;
}
public int hashCode()
{
return value[0];
}
public String toString()
{
return (value[0] != 0) ? "TRUE" : "FALSE";
}
static ASN1Boolean fromOctetString(byte[] value)
{
if (value.length != 1)
{
throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it");
}
if (value[0] == 0)
{
return FALSE;
}
else if ((value[0] & 0xff) == 0xff)
{
return TRUE;
}
else
{
return new ASN1Boolean(value);
}
}
}

View File

@ -1,28 +0,0 @@
package org.spongycastle.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.
* <p>
* If you use this interface your class should also implement the getInstance()
* pattern which takes a tag object and the tagging mode used.
* <p>
* <hr>
* <p><b>X.690</b></p>
* <p><b>8: Basic encoding rules</b></p>
* <p><b>8.13 Encoding of a choice value </b></p>
* <p>
* The encoding of a choice value shall be the same as the encoding of a value of the chosen type.
* <blockquote>
* NOTE 1 &mdash; The encoding may be primitive or constructed depending on the chosen type.
* <p>
* NOTE 2 &mdash; The tag used in the identifier octets is the tag of the chosen type,
* as specified in the ASN.1 definition of the choice type.
* </blockquote>
* </p>
*/
public interface ASN1Choice
{
// marker interface
}

View File

@ -1,13 +0,0 @@
package org.spongycastle.asn1;
/**
* Basic interface to produce serialisers for ASN.1 encodings.
*/
public interface ASN1Encodable
{
/**
* Return an object, possibly constructed, of ASN.1 primitives
* @return an ASN.1 primitive.
*/
ASN1Primitive toASN1Primitive();
}

View File

@ -1,63 +0,0 @@
package org.spongycastle.asn1;
import java.util.Enumeration;
import java.util.Vector;
/**
* Mutable class for building ASN.1 constructed objects.
*/
public class ASN1EncodableVector
{
Vector v = new Vector();
/**
* Base constructor.
*/
public ASN1EncodableVector()
{
}
/**
* Add an encodable to the vector.
*
* @param obj the encodable to add.
*/
public void add(ASN1Encodable obj)
{
v.addElement(obj);
}
/**
* Add the contents of another vector.
*
* @param other the vector to add.
*/
public void addAll(ASN1EncodableVector other)
{
for (Enumeration en = other.v.elements(); en.hasMoreElements();)
{
v.addElement(en.nextElement());
}
}
/**
* Return the object at position i in this vector.
*
* @param i the index of the object of interest.
* @return the object at position i.
*/
public ASN1Encodable get(int i)
{
return (ASN1Encodable)v.elementAt(i);
}
/**
* Return the size of the vector.
*
* @return the object count in the vector.
*/
public int size()
{
return v.size();
}
}

View File

@ -1,22 +0,0 @@
package org.spongycastle.asn1;
/**
* Supported encoding formats.
*/
public interface ASN1Encoding
{
/**
* DER - distinguished encoding rules.
*/
static final String DER = "DER";
/**
* DL - definite length encoding.
*/
static final String DL = "DL";
/**
* BER - basic encoding rules.
*/
static final String BER = "BER";
}

View File

@ -1,174 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.math.BigInteger;
import org.spongycastle.util.Arrays;
/**
* Class representing the ASN.1 ENUMERATED type.
*/
public class ASN1Enumerated
extends ASN1Primitive
{
byte[] bytes;
/**
* return an enumerated from the passed in object
*
* @param obj an ASN1Enumerated or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
* @return an ASN1Enumerated instance, or null.
*/
public static ASN1Enumerated getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1Enumerated)
{
return (ASN1Enumerated)obj;
}
if (obj instanceof byte[])
{
try
{
return (ASN1Enumerated)fromByteArray((byte[])obj);
}
catch (Exception e)
{
throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return an Enumerated from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
* @return an ASN1Enumerated instance, or null.
*/
public static ASN1Enumerated getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1Enumerated)
{
return getInstance(o);
}
else
{
return fromOctetString(((ASN1OctetString)o).getOctets());
}
}
/**
* Constructor from int.
*
* @param value the value of this enumerated.
*/
public ASN1Enumerated(
int value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
/**
* Constructor from BigInteger
*
* @param value the value of this enumerated.
*/
public ASN1Enumerated(
BigInteger value)
{
bytes = value.toByteArray();
}
/**
* Constructor from encoded BigInteger.
*
* @param bytes the value of this enumerated as an encoded BigInteger (signed).
*/
public ASN1Enumerated(
byte[] bytes)
{
this.bytes = bytes;
}
public BigInteger getValue()
{
return new BigInteger(bytes);
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeEncoded(BERTags.ENUMERATED, bytes);
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1Enumerated))
{
return false;
}
ASN1Enumerated other = (ASN1Enumerated)o;
return Arrays.areEqual(this.bytes, other.bytes);
}
public int hashCode()
{
return Arrays.hashCode(bytes);
}
private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
static ASN1Enumerated fromOctetString(byte[] enc)
{
if (enc.length > 1)
{
return new ASN1Enumerated(Arrays.clone(enc));
}
if (enc.length == 0)
{
throw new IllegalArgumentException("ENUMERATED has zero length");
}
int value = enc[0] & 0xff;
if (value >= cache.length)
{
return new ASN1Enumerated(Arrays.clone(enc));
}
ASN1Enumerated possibleMatch = cache[value];
if (possibleMatch == null)
{
possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
}
return possibleMatch;
}
}

View File

@ -1,25 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
public class ASN1Exception
extends IOException
{
private Throwable cause;
ASN1Exception(String message)
{
super(message);
}
ASN1Exception(String message, Throwable cause)
{
super(message);
this.cause = cause;
}
public Throwable getCause()
{
return cause;
}
}

View File

@ -1,373 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.Strings;
/**
* Base class representing the ASN.1 GeneralizedTime type.
* <p>
* The main difference between these and UTC time is a 4 digit year.
* </p>
*/
public class ASN1GeneralizedTime
extends ASN1Primitive
{
private byte[] time;
/**
* return a generalized time from the passed in object
*
* @param obj an ASN1GeneralizedTime or an object that can be converted into one.
* @return an ASN1GeneralizedTime instance, or null.
* @throws IllegalArgumentException if the object cannot be converted.
*/
public static ASN1GeneralizedTime getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1GeneralizedTime)
{
return (ASN1GeneralizedTime)obj;
}
if (obj instanceof byte[])
{
try
{
return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
}
catch (Exception e)
{
throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return a Generalized Time object from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @return an ASN1GeneralizedTime instance.
* @throws IllegalArgumentException if the tagged object cannot
* be converted.
*/
public static ASN1GeneralizedTime getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1GeneralizedTime)
{
return getInstance(o);
}
else
{
return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
}
}
/**
* The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
* for local time, or Z+-HHMM on the end, for difference between local
* time and UTC time. The fractional second amount f must consist of at
* least one number with trailing zeroes removed.
*
* @param time the time string.
* @throws IllegalArgumentException if String is an illegal format.
*/
public ASN1GeneralizedTime(
String time)
{
this.time = Strings.toByteArray(time);
try
{
this.getDate();
}
catch (ParseException e)
{
throw new IllegalArgumentException("invalid date string: " + e.getMessage());
}
}
/**
* Base constructor from a java.util.date object
*
* @param time a date object representing the time of interest.
*/
public ASN1GeneralizedTime(
Date time)
{
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
this.time = Strings.toByteArray(dateF.format(time));
}
/**
* Base constructor from a java.util.date and Locale - you may need to use this if the default locale
* doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
*
* @param time a date object representing the time of interest.
* @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
*/
public ASN1GeneralizedTime(
Date time,
Locale locale)
{
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", locale);
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
this.time = Strings.toByteArray(dateF.format(time));
}
ASN1GeneralizedTime(
byte[] bytes)
{
this.time = bytes;
}
/**
* Return the time.
*
* @return The time string as it appeared in the encoded object.
*/
public String getTimeString()
{
return Strings.fromByteArray(time);
}
/**
* return the time - always in the form of
* YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p/>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
* </pre>
* To read in the time and get a date which is compatible with our local
* time zone.
*/
public String getTime()
{
String stime = Strings.fromByteArray(time);
//
// standardise the format.
//
if (stime.charAt(stime.length() - 1) == 'Z')
{
return stime.substring(0, stime.length() - 1) + "GMT+00:00";
}
else
{
int signPos = stime.length() - 5;
char sign = stime.charAt(signPos);
if (sign == '-' || sign == '+')
{
return stime.substring(0, signPos)
+ "GMT"
+ stime.substring(signPos, signPos + 3)
+ ":"
+ stime.substring(signPos + 3);
}
else
{
signPos = stime.length() - 3;
sign = stime.charAt(signPos);
if (sign == '-' || sign == '+')
{
return stime.substring(0, signPos)
+ "GMT"
+ stime.substring(signPos)
+ ":00";
}
}
}
return stime + calculateGMTOffset();
}
private String calculateGMTOffset()
{
String sign = "+";
TimeZone timeZone = TimeZone.getDefault();
int offset = timeZone.getRawOffset();
if (offset < 0)
{
sign = "-";
offset = -offset;
}
int hours = offset / (60 * 60 * 1000);
int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
try
{
if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
{
hours += sign.equals("+") ? 1 : -1;
}
}
catch (ParseException e)
{
// we'll do our best and ignore daylight savings
}
return "GMT" + sign + convert(hours) + ":" + convert(minutes);
}
private String convert(int time)
{
if (time < 10)
{
return "0" + time;
}
return Integer.toString(time);
}
public Date getDate()
throws ParseException
{
SimpleDateFormat dateF;
String stime = Strings.fromByteArray(time);
String d = stime;
if (stime.endsWith("Z"))
{
if (hasFractionalSeconds())
{
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
}
else
{
dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
}
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
}
else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
{
d = this.getTime();
if (hasFractionalSeconds())
{
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
}
else
{
dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
}
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
}
else
{
if (hasFractionalSeconds())
{
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
}
else
{
dateF = new SimpleDateFormat("yyyyMMddHHmmss");
}
dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
}
if (hasFractionalSeconds())
{
// java misinterprets extra digits as being milliseconds...
String frac = d.substring(14);
int index;
for (index = 1; index < frac.length(); index++)
{
char ch = frac.charAt(index);
if (!('0' <= ch && ch <= '9'))
{
break;
}
}
if (index - 1 > 3)
{
frac = frac.substring(0, 4) + frac.substring(index);
d = d.substring(0, 14) + frac;
}
else if (index - 1 == 1)
{
frac = frac.substring(0, index) + "00" + frac.substring(index);
d = d.substring(0, 14) + frac;
}
else if (index - 1 == 2)
{
frac = frac.substring(0, index) + "0" + frac.substring(index);
d = d.substring(0, 14) + frac;
}
}
return dateF.parse(d);
}
private boolean hasFractionalSeconds()
{
for (int i = 0; i != time.length; i++)
{
if (time[i] == '.')
{
if (i == 14)
{
return true;
}
}
}
return false;
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
int length = time.length;
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeEncoded(BERTags.GENERALIZED_TIME, time);
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1GeneralizedTime))
{
return false;
}
return Arrays.areEqual(time, ((ASN1GeneralizedTime)o).time);
}
public int hashCode()
{
return Arrays.hashCode(time);
}
}

View File

@ -1,15 +0,0 @@
package org.spongycastle.asn1;
import java.io.OutputStream;
public abstract class ASN1Generator
{
protected OutputStream _out;
public ASN1Generator(OutputStream out)
{
_out = out;
}
public abstract OutputStream getRawOutputStream();
}

View File

@ -1,472 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.spongycastle.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 BERTags
{
private final int limit;
private final boolean lazyEvaluate;
private final byte[][] tmpBuffers;
public ASN1InputStream(
InputStream is)
{
this(is, StreamUtil.findLimit(is));
}
/**
* 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 lazyEvaluate true if parsing inside constructed objects can be delayed.
*/
public ASN1InputStream(
InputStream input,
boolean lazyEvaluate)
{
this(input, StreamUtil.findLimit(input), lazyEvaluate);
}
/**
* 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;
this.tmpBuffers = new byte[11][];
}
int getLimit()
{
return limit;
}
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.
*
* @param tag the full tag details.
* @param tagNo the tagNo defined.
* @param length the length of the object.
* @return the resulting primitive.
* @throws java.io.IOException on processing exception.
*/
protected ASN1Primitive buildObject(
int tag,
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 ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
}
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...
//
ASN1EncodableVector v = buildDEREncodableVector(defIn);
ASN1OctetString[] strings = new ASN1OctetString[v.size()];
for (int i = 0; i != strings.length; i++)
{
strings[i] = (ASN1OctetString)v.get(i);
}
return new BEROctetString(strings);
case SEQUENCE:
if (lazyEvaluate)
{
return new LazyEncodedSequence(defIn.toByteArray());
}
else
{
return DERFactory.createSequence(buildDEREncodableVector(defIn));
}
case SET:
return DERFactory.createSet(buildDEREncodableVector(defIn));
case EXTERNAL:
return new DERExternal(buildDEREncodableVector(defIn));
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
}
return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
}
ASN1EncodableVector buildEncodableVector()
throws IOException
{
ASN1EncodableVector v = new ASN1EncodableVector();
ASN1Primitive o;
while ((o = readObject()) != null)
{
v.add(o);
}
return v;
}
ASN1EncodableVector buildDEREncodableVector(
DefiniteLengthInputStream dIn) throws IOException
{
return new ASN1InputStream(dIn).buildEncodableVector();
}
public ASN1Primitive 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, limit);
ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
if ((tag & APPLICATION) != 0)
{
return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
}
if ((tag & TAGGED) != 0)
{
return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
}
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagNo)
{
case OCTET_STRING:
return new BEROctetStringParser(sp).getLoadedObject();
case SEQUENCE:
return new BERSequenceParser(sp).getLoadedObject();
case SET:
return new BERSetParser(sp).getLoadedObject();
case EXTERNAL:
return new DERExternalParser(sp).getLoadedObject();
default:
throw new IOException("unknown BER object encountered");
}
}
else
{
try
{
return buildObject(tag, tagNo, length);
}
catch (IllegalArgumentException e)
{
throw new ASN1Exception("corrupted stream detected", e);
}
}
}
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;
// Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
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;
}
private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
throws IOException
{
int len = defIn.getRemaining();
if (defIn.getRemaining() < tmpBuffers.length)
{
byte[] buf = tmpBuffers[len];
if (buf == null)
{
buf = tmpBuffers[len] = new byte[len];
}
Streams.readFully(defIn, buf);
return buf;
}
else
{
return defIn.toByteArray();
}
}
private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
throws IOException
{
int len = defIn.getRemaining() / 2;
char[] buf = new char[len];
int totalRead = 0;
while (totalRead < len)
{
int ch1 = defIn.read();
if (ch1 < 0)
{
break;
}
int ch2 = defIn.read();
if (ch2 < 0)
{
break;
}
buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
}
return buf;
}
static ASN1Primitive createPrimitiveDERObject(
int tagNo,
DefiniteLengthInputStream defIn,
byte[][] tmpBuffers)
throws IOException
{
switch (tagNo)
{
case BIT_STRING:
return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
case BMP_STRING:
return new DERBMPString(getBMPCharBuffer(defIn));
case BOOLEAN:
return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
case ENUMERATED:
return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
case GENERALIZED_TIME:
return new ASN1GeneralizedTime(defIn.toByteArray());
case GENERAL_STRING:
return new DERGeneralString(defIn.toByteArray());
case IA5_STRING:
return new DERIA5String(defIn.toByteArray());
case INTEGER:
return new ASN1Integer(defIn.toByteArray(), false);
case NULL:
return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
case NUMERIC_STRING:
return new DERNumericString(defIn.toByteArray());
case OBJECT_IDENTIFIER:
return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
case OCTET_STRING:
return new DEROctetString(defIn.toByteArray());
case PRINTABLE_STRING:
return new DERPrintableString(defIn.toByteArray());
case T61_STRING:
return new DERT61String(defIn.toByteArray());
case UNIVERSAL_STRING:
return new DERUniversalString(defIn.toByteArray());
case UTC_TIME:
return new ASN1UTCTime(defIn.toByteArray());
case UTF8_STRING:
return new DERUTF8String(defIn.toByteArray());
case VISIBLE_STRING:
return new DERVisibleString(defIn.toByteArray());
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
}
}

View File

@ -1,157 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.math.BigInteger;
import org.spongycastle.util.Arrays;
/**
* Class representing the ASN.1 INTEGER type.
*/
public class ASN1Integer
extends ASN1Primitive
{
byte[] bytes;
/**
* return an integer from the passed in object
*
* @param obj an ASN1Integer or an object that can be converted into one.
* @throws IllegalArgumentException if the object cannot be converted.
* @return an ASN1Integer instance.
*/
public static ASN1Integer getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1Integer)
{
return (ASN1Integer)obj;
}
if (obj instanceof byte[])
{
try
{
return (ASN1Integer)fromByteArray((byte[])obj);
}
catch (Exception e)
{
throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return an Integer from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @throws IllegalArgumentException if the tagged object cannot
* be converted.
* @return an ASN1Integer instance.
*/
public static ASN1Integer getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1Integer)
{
return getInstance(o);
}
else
{
return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
}
}
public ASN1Integer(
long value)
{
bytes = BigInteger.valueOf(value).toByteArray();
}
public ASN1Integer(
BigInteger value)
{
bytes = value.toByteArray();
}
public ASN1Integer(
byte[] bytes)
{
this(bytes, true);
}
ASN1Integer(byte[] bytes, boolean clone)
{
this.bytes = (clone) ? Arrays.clone(bytes) : bytes;
}
public BigInteger getValue()
{
return new BigInteger(bytes);
}
/**
* in some cases positive values get crammed into a space,
* that's not quite big enough...
* @return the BigInteger that results from treating this ASN.1 INTEGER as unsigned.
*/
public BigInteger getPositiveValue()
{
return new BigInteger(1, bytes);
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeEncoded(BERTags.INTEGER, bytes);
}
public int hashCode()
{
int value = 0;
for (int i = 0; i != bytes.length; i++)
{
value ^= (bytes[i] & 0xff) << (i % 4);
}
return value;
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1Integer))
{
return false;
}
ASN1Integer other = (ASN1Integer)o;
return Arrays.areEqual(bytes, other.bytes);
}
public String toString()
{
return getValue().toString();
}
}

View File

@ -1,75 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
/**
* A NULL object - use DERNull.INSTANCE for populating structures.
*/
public abstract class ASN1Null
extends ASN1Primitive
{
/**
* Return an instance of ASN.1 NULL from the passed in object.
* <p>
* Accepted inputs:
* <ul>
* <li> null &rarr; null
* <li> {@link ASN1Null} object
* <li> a byte[] containing ASN.1 NULL object
* </ul>
* </p>
*
* @param o object to be converted.
* @return an instance of ASN1Null, or null.
* @exception IllegalArgumentException if the object cannot be converted.
*/
public static ASN1Null getInstance(Object o)
{
if (o instanceof ASN1Null)
{
return (ASN1Null)o;
}
if (o != null)
{
try
{
return ASN1Null.getInstance(ASN1Primitive.fromByteArray((byte[])o));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct NULL from byte[]: " + e.getMessage());
}
catch (ClassCastException e)
{
throw new IllegalArgumentException("unknown object in getInstance(): " + o.getClass().getName());
}
}
return null;
}
public int hashCode()
{
return -1;
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1Null))
{
return false;
}
return true;
}
abstract void encode(ASN1OutputStream out)
throws IOException;
public String toString()
{
return "NULL";
}
}

View File

@ -1,111 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Base class for defining an ASN.1 object.
*/
public abstract class ASN1Object
implements ASN1Encodable
{
/**
* Return the default BER or DER encoding for this object.
*
* @return BER/DER byte encoded object.
* @throws java.io.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(ASN1Encoding.DER))
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
dOut.writeObject(this);
return bOut.toByteArray();
}
else if (encoding.equals(ASN1Encoding.DL))
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DLOutputStream dOut = new DLOutputStream(bOut);
dOut.writeObject(this);
return bOut.toByteArray();
}
return this.getEncoded();
}
public int hashCode()
{
return this.toASN1Primitive().hashCode();
}
public boolean equals(
Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof ASN1Encodable))
{
return false;
}
ASN1Encodable other = (ASN1Encodable)o;
return this.toASN1Primitive().equals(other.toASN1Primitive());
}
/**
* @deprecated use toASN1Primitive()
* @return the underlying primitive type.
*/
public ASN1Primitive toASN1Object()
{
return this.toASN1Primitive();
}
/**
* Return true if obj is a byte array and represents an object with the given tag value.
*
* @param obj object of interest.
* @param tagValue tag value to check for.
* @return true if obj is a byte encoding starting with the given tag value, false otherwise.
*/
protected static boolean hasEncodedTagValue(Object obj, int tagValue)
{
return (obj instanceof byte[]) && ((byte[])obj)[0] == tagValue;
}
/**
* Method providing a primitive representation of this object suitable for encoding.
* @return a primitive representation of this object.
*/
public abstract ASN1Primitive toASN1Primitive();
}

View File

@ -1,472 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import org.spongycastle.util.Arrays;
/**
* Class representing the ASN.1 OBJECT IDENTIFIER type.
*/
public class ASN1ObjectIdentifier
extends ASN1Primitive
{
String identifier;
private byte[] body;
/**
* return an OID from the passed in object
* @param obj an ASN1ObjectIdentifier or an object that can be converted into one.
* @throws IllegalArgumentException if the object cannot be converted.
* @return an ASN1ObjectIdentifier instance, or null.
*/
public static ASN1ObjectIdentifier getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1ObjectIdentifier)
{
return (ASN1ObjectIdentifier)obj;
}
if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
{
return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
}
if (obj instanceof byte[])
{
byte[] enc = (byte[])obj;
try
{
return (ASN1ObjectIdentifier)fromByteArray(enc);
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct object identifier from byte[]: " + e.getMessage());
}
}
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.
* @throws IllegalArgumentException if the tagged object cannot
* be converted.
* @return an ASN1ObjectIdentifier instance, or null.
*/
public static ASN1ObjectIdentifier getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1ObjectIdentifier)
{
return getInstance(o);
}
else
{
return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
}
}
private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
ASN1ObjectIdentifier(
byte[] bytes)
{
StringBuffer objId = new StringBuffer();
long value = 0;
BigInteger bigValue = null;
boolean first = true;
for (int i = 0; i != bytes.length; i++)
{
int b = bytes[i] & 0xff;
if (value <= LONG_LIMIT)
{
value += (b & 0x7f);
if ((b & 0x80) == 0) // end of number reached
{
if (first)
{
if (value < 40)
{
objId.append('0');
}
else if (value < 80)
{
objId.append('1');
value -= 40;
}
else
{
objId.append('2');
value -= 80;
}
first = false;
}
objId.append('.');
objId.append(value);
value = 0;
}
else
{
value <<= 7;
}
}
else
{
if (bigValue == null)
{
bigValue = BigInteger.valueOf(value);
}
bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
if ((b & 0x80) == 0)
{
if (first)
{
objId.append('2');
bigValue = bigValue.subtract(BigInteger.valueOf(80));
first = false;
}
objId.append('.');
objId.append(bigValue);
bigValue = null;
value = 0;
}
else
{
bigValue = bigValue.shiftLeft(7);
}
}
}
this.identifier = objId.toString();
this.body = Arrays.clone(bytes);
}
/**
* Create an OID based on the passed in String.
*
* @param identifier a string representation of an OID.
*/
public ASN1ObjectIdentifier(
String identifier)
{
if (identifier == null)
{
throw new IllegalArgumentException("'identifier' cannot be null");
}
if (!isValidIdentifier(identifier))
{
throw new IllegalArgumentException("string " + identifier + " not an OID");
}
this.identifier = identifier;
}
/**
* Create an OID that creates a branch under the current one.
*
* @param branchID node numbers for the new branch.
* @return the OID for the new created branch.
*/
ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branchID)
{
if (!isValidBranchID(branchID, 0))
{
throw new IllegalArgumentException("string " + branchID + " not a valid OID branch");
}
this.identifier = oid.getId() + "." + branchID;
}
/**
* Return the OID as a string.
*
* @return the string representation of the OID carried by this object.
*/
public String getId()
{
return identifier;
}
/**
* Return an OID that creates a branch under the current one.
*
* @param branchID node numbers for the new branch.
* @return the OID for the new created branch.
*/
public ASN1ObjectIdentifier branch(String branchID)
{
return new ASN1ObjectIdentifier(this, branchID);
}
/**
* Return true if this oid is an extension of the passed in branch, stem.
*
* @param stem the arc or branch that is a possible parent.
* @return true if the branch is on the passed in stem, false otherwise.
*/
public boolean on(ASN1ObjectIdentifier stem)
{
String id = getId(), stemId = stem.getId();
return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
}
private void writeField(
ByteArrayOutputStream out,
long fieldValue)
{
byte[] result = new byte[9];
int pos = 8;
result[pos] = (byte)((int)fieldValue & 0x7f);
while (fieldValue >= (1L << 7))
{
fieldValue >>= 7;
result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
}
out.write(result, pos, 9 - pos);
}
private void writeField(
ByteArrayOutputStream out,
BigInteger fieldValue)
{
int byteCount = (fieldValue.bitLength() + 6) / 7;
if (byteCount == 0)
{
out.write(0);
}
else
{
BigInteger tmpValue = fieldValue;
byte[] tmp = new byte[byteCount];
for (int i = byteCount - 1; i >= 0; i--)
{
tmp[i] = (byte)((tmpValue.intValue() & 0x7f) | 0x80);
tmpValue = tmpValue.shiftRight(7);
}
tmp[byteCount - 1] &= 0x7f;
out.write(tmp, 0, tmp.length);
}
}
private void doOutput(ByteArrayOutputStream aOut)
{
OIDTokenizer tok = new OIDTokenizer(identifier);
int first = Integer.parseInt(tok.nextToken()) * 40;
String secondToken = tok.nextToken();
if (secondToken.length() <= 18)
{
writeField(aOut, first + Long.parseLong(secondToken));
}
else
{
writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
}
while (tok.hasMoreTokens())
{
String token = tok.nextToken();
if (token.length() <= 18)
{
writeField(aOut, Long.parseLong(token));
}
else
{
writeField(aOut, new BigInteger(token));
}
}
}
protected synchronized byte[] getBody()
{
if (body == null)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
doOutput(bOut);
body = bOut.toByteArray();
}
return body;
}
boolean isConstructed()
{
return false;
}
int encodedLength()
throws IOException
{
int length = getBody().length;
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
byte[] enc = getBody();
out.write(BERTags.OBJECT_IDENTIFIER);
out.writeLength(enc.length);
out.write(enc);
}
public int hashCode()
{
return identifier.hashCode();
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1ObjectIdentifier))
{
return false;
}
return identifier.equals(((ASN1ObjectIdentifier)o).identifier);
}
public String toString()
{
return getId();
}
private static boolean isValidBranchID(
String branchID, int start)
{
boolean periodAllowed = false;
int pos = branchID.length();
while (--pos >= start)
{
char ch = branchID.charAt(pos);
// TODO Leading zeroes?
if ('0' <= ch && ch <= '9')
{
periodAllowed = true;
continue;
}
if (ch == '.')
{
if (!periodAllowed)
{
return false;
}
periodAllowed = false;
continue;
}
return false;
}
return periodAllowed;
}
private static boolean isValidIdentifier(
String identifier)
{
if (identifier.length() < 3 || identifier.charAt(1) != '.')
{
return false;
}
char first = identifier.charAt(0);
if (first < '0' || first > '2')
{
return false;
}
return isValidBranchID(identifier, 2);
}
private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
static ASN1ObjectIdentifier fromOctetString(byte[] enc)
{
if (enc.length < 3)
{
return new ASN1ObjectIdentifier(enc);
}
int idx1 = enc[enc.length - 2] & 0xff;
// in this case top bit is always zero
int idx2 = enc[enc.length - 1] & 0x7f;
ASN1ObjectIdentifier possibleMatch;
synchronized (cache)
{
ASN1ObjectIdentifier[] first = cache[idx1];
if (first == null)
{
first = cache[idx1] = new ASN1ObjectIdentifier[128];
}
possibleMatch = first[idx2];
if (possibleMatch == null)
{
return first[idx2] = new ASN1ObjectIdentifier(enc);
}
if (Arrays.areEqual(enc, possibleMatch.getBody()))
{
return possibleMatch;
}
idx1 = (idx1 + 1) & 0xff;
first = cache[idx1];
if (first == null)
{
first = cache[idx1] = new ASN1ObjectIdentifier[128];
}
possibleMatch = first[idx2];
if (possibleMatch == null)
{
return first[idx2] = new ASN1ObjectIdentifier(enc);
}
if (Arrays.areEqual(enc, possibleMatch.getBody()))
{
return possibleMatch;
}
idx2 = (idx2 + 1) & 0x7f;
possibleMatch = first[idx2];
if (possibleMatch == null)
{
return first[idx2] = new ASN1ObjectIdentifier(enc);
}
}
if (Arrays.areEqual(enc, possibleMatch.getBody()))
{
return possibleMatch;
}
return new ASN1ObjectIdentifier(enc);
}
}

View File

@ -1,251 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.encoders.Hex;
/**
* Abstract base for the ASN.1 OCTET STRING data type
* <p>
* This supports BER, and DER forms of the data.
* </p><p>
* DER form is always primitive single OCTET STRING, while
* BER support includes the constructed forms.
* </p>
* <hr>
* <p><b>X.690</b></p>
* <p><b>8: Basic encoding rules</b></p>
* <p><b>8.7 Encoding of an octetstring value</b></p>
* <p>
* <b>8.7.1</b> The encoding of an octetstring value shall be
* either primitive or constructed at the option of the sender.
* <blockquote>
* NOTE &mdash; Where it is necessary to transfer part of an octet string
* before the entire OCTET STRING is available, the constructed encoding
* is used.
* </blockquote>
* <p>
* <b>8.7.2</b> The primitive encoding contains zero,
* one or more contents octets equal in value to the octets
* in the data value, in the order they appear in the data value,
* and with the most significant bit of an octet of the data value
* aligned with the most significant bit of an octet of the contents octets.
* </p>
* <p>
* <b>8.7.3</b> The contents octets for the constructed encoding shall consist
* of zero, one, or more encodings.
* <blockquote>
* NOTE &mdash; Each such encoding includes identifier, length, and contents octets,
* and may include end-of-contents octets if it is constructed.
* </blockquote>
* </p>
* <p>
* <b>8.7.3.1</b> To encode an octetstring value in this way,
* it is segmented. Each segment shall consist of a series of
* consecutive octets of the value. There shall be no significance
* placed on the segment boundaries.
* <blockquote>
* NOTE &mdash; A segment may be of size zero, i.e. contain no octets.
* </blockquote>
* </p>
* <p>
* <b>8.7.3.2</b> Each encoding in the contents octets shall represent
* a segment of the overall octetstring, the encoding arising from
* a recursive application of this subclause.
* In this recursive application, each segment is treated as if it were
* a octetstring value. The encodings of the segments shall appear in the contents
* octets in the order in which their octets appear in the overall value.
* <blockquote>
* NOTE 1 &mdash; As a consequence of this recursion,
* each encoding in the contents octets may itself
* be primitive or constructed.
* However, such encodings will usually be primitive.
* </p><p>
* NOTE 2 &mdash; In particular, the tags in the contents octets are always universal class, number 4.
* </blockquote>
* </p>
* <p><b>9: Canonical encoding rules</b></p>
* <p><b>9.1 Length forms</b></p>
* <p>
* If the encoding is constructed, it shall employ the indefinite length form.
* If the encoding is primitive, it shall include the fewest length octets necessary.
* [Contrast with 8.1.3.2 b).]
* </p>
* <p><b>9.2 String encoding forms</b></p>
* <p>
* BIT STRING, OCTET STRING,and restricted character string
* values shall be encoded with a primitive encoding if they would
* require no more than 1000 contents octets, and as a constructed
* encoding otherwise. The string fragments contained in
* the constructed encoding shall be encoded with a primitive encoding.
* The encoding of each fragment, except possibly
* the last, shall have 1000 contents octets. (Contrast with 8.21.6.)
* </p>
* <b>10: Distinguished encoding rules</b>
* </p><p>
* <b>10.1 Length forms</b>
* The definite form of length encoding shall be used,
* encoded in the minimum number of octets.
* [Contrast with 8.1.3.2 b).]
* </p><p>
* <b>10.2 String encoding forms</b>
* For BIT STRING, OCTET STRING and restricted character string types,
* the constructed form of encoding shall not be used.
* (Contrast with 8.21.6.)
* </p>
*/
public abstract class ASN1OctetString
extends ASN1Primitive
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)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof ASN1OctetString)
{
return getInstance(o);
}
else
{
return BEROctetString.fromSequence(ASN1Sequence.getInstance(o));
}
}
/**
* return an Octet String from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
*/
public static ASN1OctetString getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1OctetString)
{
return (ASN1OctetString)obj;
}
else if (obj instanceof byte[])
{
try
{
return ASN1OctetString.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage());
}
}
else if (obj instanceof ASN1Encodable)
{
ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
if (primitive instanceof ASN1OctetString)
{
return (ASN1OctetString)primitive;
}
}
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;
}
/**
* Return the content of the OCTET STRING as an InputStream.
*
* @return an InputStream representing the OCTET STRING's content.
*/
public InputStream getOctetStream()
{
return new ByteArrayInputStream(string);
}
/**
* Return the parser associated with this object.
*
* @return a parser based on this OCTET STRING
*/
public ASN1OctetStringParser parser()
{
return this;
}
/**
* Return the content of the OCTET STRING as a byte array.
*
* @return the byte[] representing the OCTET STRING's content.
*/
public byte[] getOctets()
{
return string;
}
public int hashCode()
{
return Arrays.hashCode(this.getOctets());
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1OctetString))
{
return false;
}
ASN1OctetString other = (ASN1OctetString)o;
return Arrays.areEqual(string, other.string);
}
public ASN1Primitive getLoadedObject()
{
return this.toASN1Primitive();
}
ASN1Primitive toDERObject()
{
return new DEROctetString(string);
}
ASN1Primitive toDLObject()
{
return new DEROctetString(string);
}
abstract void encode(ASN1OutputStream out)
throws IOException;
public String toString()
{
return "#"+new String(Hex.encode(string));
}
}

View File

@ -1,17 +0,0 @@
package org.spongycastle.asn1;
import java.io.InputStream;
/**
* A basic parser for an OCTET STRING object
*/
public interface ASN1OctetStringParser
extends ASN1Encodable, InMemoryRepresentable
{
/**
* Return the content of the OCTET STRING as an InputStream.
*
* @return an InputStream representing the OCTET STRING's content.
*/
public InputStream getOctetStream();
}

View File

@ -1,194 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.io.OutputStream;
/**
* Stream that produces output based on the default encoding for the passed in objects.
*/
public class ASN1OutputStream
{
private OutputStream os;
public ASN1OutputStream(
OutputStream os)
{
this.os = os;
}
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 write(int b)
throws IOException
{
os.write(b);
}
void write(byte[] bytes)
throws IOException
{
os.write(bytes);
}
void write(byte[] bytes, int off, int len)
throws IOException
{
os.write(bytes, off, len);
}
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
{
os.write(BERTags.NULL);
os.write(0x00);
}
public void writeObject(
ASN1Encodable obj)
throws IOException
{
if (obj != null)
{
obj.toASN1Primitive().encode(this);
}
else
{
throw new IOException("null object detected");
}
}
void writeImplicitObject(ASN1Primitive obj)
throws IOException
{
if (obj != null)
{
obj.encode(new ImplicitOutputStream(os));
}
else
{
throw new IOException("null object detected");
}
}
public void close()
throws IOException
{
os.close();
}
public void flush()
throws IOException
{
os.flush();
}
ASN1OutputStream getDERSubStream()
{
return new DEROutputStream(os);
}
ASN1OutputStream getDLSubStream()
{
return new DLOutputStream(os);
}
private class ImplicitOutputStream
extends ASN1OutputStream
{
private boolean first = true;
public ImplicitOutputStream(OutputStream os)
{
super(os);
}
public void write(int b)
throws IOException
{
if (first)
{
first = false;
}
else
{
super.write(b);
}
}
}
}

View File

@ -1,23 +0,0 @@
package org.spongycastle.asn1;
public class ASN1ParsingException
extends IllegalStateException
{
private Throwable cause;
public ASN1ParsingException(String message)
{
super(message);
}
public ASN1ParsingException(String message, Throwable cause)
{
super(message);
this.cause = cause;
}
public Throwable getCause()
{
return cause;
}
}

View File

@ -1,82 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
/**
* Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings.
*/
public abstract class ASN1Primitive
extends ASN1Object
{
ASN1Primitive()
{
}
/**
* 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 ASN1Primitive fromByteArray(byte[] data)
throws IOException
{
ASN1InputStream aIn = new ASN1InputStream(data);
try
{
return aIn.readObject();
}
catch (ClassCastException e)
{
throw new IOException("cannot recognise object in stream");
}
}
public final boolean equals(Object o)
{
if (this == o)
{
return true;
}
return (o instanceof ASN1Encodable) && asn1Equals(((ASN1Encodable)o).toASN1Primitive());
}
public ASN1Primitive toASN1Primitive()
{
return this;
}
/**
* Return the current object as one which encodes using Distinguished Encoding Rules.
*
* @return a DER version of this.
*/
ASN1Primitive toDERObject()
{
return this;
}
/**
* Return the current object as one which encodes using Definite Length encoding.
*
* @return a DL version of this.
*/
ASN1Primitive toDLObject()
{
return this;
}
public abstract int hashCode();
abstract boolean isConstructed();
abstract int encodedLength() throws IOException;
abstract void encode(ASN1OutputStream out) throws IOException;
abstract boolean asn1Equals(ASN1Primitive o);
}

View File

@ -1,382 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
/**
* ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs.
* <p>
* DER form is always definite form length fields, while
* BER support uses indefinite form.
* <hr>
* <p><b>X.690</b></p>
* <p><b>8: Basic encoding rules</b></p>
* <p><b>8.9 Encoding of a sequence value </b></p>
* 8.9.1 The encoding of a sequence value shall be constructed.
* <p>
* <b>8.9.2</b> The contents octets shall consist of the complete
* encoding of one data value from each of the types listed in
* the ASN.1 definition of the sequence type, in the order of
* their appearance in the definition, unless the type was referenced
* with the keyword <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
* </p><p>
* <b>8.9.3</b> The encoding of a data value may, but need not,
* be present for a type which was referenced with the keyword
* <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
* If present, it shall appear in the encoding at the point
* corresponding to the appearance of the type in the ASN.1 definition.
* </p><p>
* <b>8.10 Encoding of a sequence-of value </b>
* </p><p>
* <b>8.10.1</b> The encoding of a sequence-of value shall be constructed.
* <p>
* <b>8.10.2</b> The contents octets shall consist of zero,
* one or more complete encodings of data values from the type listed in
* the ASN.1 definition.
* <p>
* <b>8.10.3</b> The order of the encodings of the data values shall be
* the same as the order of the data values in the sequence-of value to
* be encoded.
* </p>
* <p><b>9: Canonical encoding rules</b></p>
* <p><b>9.1 Length forms</b></p>
* If the encoding is constructed, it shall employ the indefinite length form.
* If the encoding is primitive, it shall include the fewest length octets necessary.
* [Contrast with 8.1.3.2 b).]
*
* <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
* <p><b>11.5 Set and sequence components with default value</b></p>
* The encoding of a set value or sequence value shall not include
* an encoding for any component value which is equal to
* its default value.
*/
public abstract class ASN1Sequence
extends ASN1Primitive
{
protected Vector seq = new Vector();
/**
* Return an ASN1Sequence from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
* @return an ASN1Sequence instance, or null.
*/
public static ASN1Sequence getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1Sequence)
{
return (ASN1Sequence)obj;
}
else if (obj instanceof ASN1SequenceParser)
{
return ASN1Sequence.getInstance(((ASN1SequenceParser)obj).toASN1Primitive());
}
else if (obj instanceof byte[])
{
try
{
return ASN1Sequence.getInstance(fromByteArray((byte[])obj));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
}
}
else if (obj instanceof ASN1Encodable)
{
ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
if (primitive instanceof ASN1Sequence)
{
return (ASN1Sequence)primitive;
}
}
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 <b>should</b>
* 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.
* @return an ASN1Sequence instance.
*/
public static ASN1Sequence getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
if (explicit)
{
if (!obj.isExplicit())
{
throw new IllegalArgumentException("object implicit - explicit expected.");
}
return ASN1Sequence.getInstance(obj.getObject().toASN1Primitive());
}
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 DLSequence(obj.getObject());
}
}
else
{
if (obj.getObject() instanceof ASN1Sequence)
{
return (ASN1Sequence)obj.getObject();
}
}
}
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
}
/**
* Create an empty sequence
*/
protected ASN1Sequence()
{
}
/**
* Create a sequence containing one object
* @param obj the object to be put in the SEQUENCE.
*/
protected ASN1Sequence(
ASN1Encodable obj)
{
seq.addElement(obj);
}
/**
* Create a sequence containing a vector of objects.
* @param v the vector of objects to be put in the SEQUENCE
*/
protected ASN1Sequence(
ASN1EncodableVector v)
{
for (int i = 0; i != v.size(); i++)
{
seq.addElement(v.get(i));
}
}
/**
* Create a sequence containing a vector of objects.
*/
protected ASN1Sequence(
ASN1Encodable[] array)
{
for (int i = 0; i != array.length; i++)
{
seq.addElement(array[i]);
}
}
public ASN1Encodable[] toArray()
{
ASN1Encodable[] values = new ASN1Encodable[this.size()];
for (int i = 0; i != this.size(); i++)
{
values[i] = this.getObjectAt(i);
}
return values;
}
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 ASN1Encodable readObject() throws IOException
{
if (index == max)
{
return null;
}
ASN1Encodable obj = getObjectAt(index++);
if (obj instanceof ASN1Sequence)
{
return ((ASN1Sequence)obj).parser();
}
if (obj instanceof ASN1Set)
{
return ((ASN1Set)obj).parser();
}
return obj;
}
public ASN1Primitive getLoadedObject()
{
return outer;
}
public ASN1Primitive toASN1Primitive()
{
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 ASN1Encodable getObjectAt(
int index)
{
return (ASN1Encodable)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 = getNext(e);
hashCode *= 17;
hashCode ^= o.hashCode();
}
return hashCode;
}
boolean asn1Equals(
ASN1Primitive 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())
{
ASN1Encodable obj1 = getNext(s1);
ASN1Encodable obj2 = getNext(s2);
ASN1Primitive o1 = obj1.toASN1Primitive();
ASN1Primitive o2 = obj2.toASN1Primitive();
if (o1 == o2 || o1.equals(o2))
{
continue;
}
return false;
}
return true;
}
private ASN1Encodable getNext(Enumeration e)
{
ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
return encObj;
}
/**
* Change current SEQUENCE object to be encoded as {@link DERSequence}.
* This is part of Distinguished Encoding Rules form serialization.
*/
ASN1Primitive toDERObject()
{
ASN1Sequence derSeq = new DERSequence();
derSeq.seq = this.seq;
return derSeq;
}
/**
* Change current SEQUENCE object to be encoded as {@link DLSequence}.
* This is part of Direct Length form serialization.
*/
ASN1Primitive toDLObject()
{
ASN1Sequence dlSeq = new DLSequence();
dlSeq.seq = this.seq;
return dlSeq;
}
boolean isConstructed()
{
return true;
}
abstract void encode(ASN1OutputStream out)
throws IOException;
public String toString()
{
return seq.toString();
}
}

View File

@ -1,19 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
/**
* A basic parser for a SEQUENCE object
*/
public interface ASN1SequenceParser
extends ASN1Encodable, InMemoryRepresentable
{
/**
* Read the next object from the underlying object representing a SEQUENCE.
*
* @throws IOException for bad input stream.
* @return the next object, null if we are at the end.
*/
ASN1Encodable readObject()
throws IOException;
}

View File

@ -1,560 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
/**
* ASN.1 <code>SET</code> and <code>SET OF</code> constructs.
* <p>
* Note: This does not know which syntax the set is!
* (The difference: ordering of SET elements or not ordering.)
* <p>
* DER form is always definite form length fields, while
* BER support uses indefinite form.
* <p>
* The CER form support does not exist.
* <p>
* <hr>
* <h2>X.690</h2>
* <h3>8: Basic encoding rules</h3>
* <h4>8.11 Encoding of a set value </h4>
* <b>8.11.1</b> The encoding of a set value shall be constructed
* <p>
* <b>8.11.2</b> The contents octets shall consist of the complete
* encoding of a data value from each of the types listed in the
* ASN.1 definition of the set type, in an order chosen by the sender,
* unless the type was referenced with the keyword
* <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
* <p>
* <b>8.11.3</b> The encoding of a data value may, but need not,
* be present for a type which was referenced with the keyword
* <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>.
* <blockquote>
* NOTE &mdash; The order of data values in a set value is not significant,
* and places no constraints on the order during transfer
* </blockquote>
* <h4>8.12 Encoding of a set-of value</h4>
* <b>8.12.1</b> The encoding of a set-of value shall be constructed.
* <p>
* <b>8.12.2</b> The text of 8.10.2 applies:
* <i>The contents octets shall consist of zero,
* one or more complete encodings of data values from the type listed in
* the ASN.1 definition.</i>
* <p>
* <b>8.12.3</b> The order of data values need not be preserved by
* the encoding and subsequent decoding.
*
* <h3>9: Canonical encoding rules</h3>
* <h4>9.1 Length forms</h4>
* If the encoding is constructed, it shall employ the indefinite length form.
* If the encoding is primitive, it shall include the fewest length octets necessary.
* [Contrast with 8.1.3.2 b).]
* <h4>9.3 Set components</h4>
* The encodings of the component values of a set value shall
* appear in an order determined by their tags as specified
* in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
* Additionally, for the purposes of determining the order in which
* components are encoded when one or more component is an untagged
* choice type, each untagged choice type is ordered as though it
* has a tag equal to that of the smallest tag in that choice type
* or any untagged choice types nested within.
*
* <h3>10: Distinguished encoding rules</h3>
* <h4>10.1 Length forms</h4>
* The definite form of length encoding shall be used,
* encoded in the minimum number of octets.
* [Contrast with 8.1.3.2 b).]
* <h4>10.3 Set components</h4>
* The encodings of the component values of a set value shall appear
* in an order determined by their tags as specified
* in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1.
* <blockquote>
* NOTE &mdash; Where a component of the set is an untagged choice type,
* the location of that component in the ordering will depend on
* the tag of the choice component being encoded.
* </blockquote>
*
* <h3>11: Restrictions on BER employed by both CER and DER</h3>
* <h4>11.5 Set and sequence components with default value </h4>
* The encoding of a set value or sequence value shall not include
* an encoding for any component value which is equal to
* its default value.
* <h4>11.6 Set-of components </h4>
* <p>
* The encodings of the component values of a set-of value
* shall appear in ascending order, the encodings being compared
* as octet strings with the shorter components being padded at
* their trailing end with 0-octets.
* <blockquote>
* NOTE &mdash; The padding octets are for comparison purposes only
* and do not appear in the encodings.
* </blockquote>
*/
public abstract class ASN1Set
extends ASN1Primitive
{
private Vector set = new Vector();
private boolean isSorted = false;
/**
* return an ASN1Set from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
* @return an ASN1Set instance, or null.
*/
public static ASN1Set getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1Set)
{
return (ASN1Set)obj;
}
else if (obj instanceof ASN1SetParser)
{
return ASN1Set.getInstance(((ASN1SetParser)obj).toASN1Primitive());
}
else if (obj instanceof byte[])
{
try
{
return ASN1Set.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct set from byte[]: " + e.getMessage());
}
}
else if (obj instanceof ASN1Encodable)
{
ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
if (primitive instanceof ASN1Set)
{
return (ASN1Set)primitive;
}
}
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 <b>should</b>
* 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.
* @return an ASN1Set instance.
*/
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 set.
//
if (obj.isExplicit())
{
if (obj instanceof BERTaggedObject)
{
return new BERSet(obj.getObject());
}
else
{
return new DLSet(obj.getObject());
}
}
else
{
if (obj.getObject() instanceof ASN1Set)
{
return (ASN1Set)obj.getObject();
}
//
// in this case the parser returns a sequence, convert it
// into a set.
//
if (obj.getObject() instanceof ASN1Sequence)
{
ASN1Sequence s = (ASN1Sequence)obj.getObject();
if (obj instanceof BERTaggedObject)
{
return new BERSet(s.toArray());
}
else
{
return new DLSet(s.toArray());
}
}
}
}
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
}
protected ASN1Set()
{
}
/**
* create a sequence containing one object
* @param obj object to be added to the SET.
*/
protected ASN1Set(
ASN1Encodable obj)
{
set.addElement(obj);
}
/**
* create a sequence containing a vector of objects.
* @param v a vector of objects to make up the SET.
* @param doSort true if should be sorted DER style, false otherwise.
*/
protected ASN1Set(
ASN1EncodableVector v,
boolean doSort)
{
for (int i = 0; i != v.size(); i++)
{
set.addElement(v.get(i));
}
if (doSort)
{
this.sort();
}
}
/**
* create a sequence containing a vector of objects.
*/
protected ASN1Set(
ASN1Encodable[] array,
boolean doSort)
{
for (int i = 0; i != array.length; i++)
{
set.addElement(array[i]);
}
if (doSort)
{
this.sort();
}
}
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 ASN1Encodable getObjectAt(
int index)
{
return (ASN1Encodable)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 ASN1Encodable[] toArray()
{
ASN1Encodable[] values = new ASN1Encodable[this.size()];
for (int i = 0; i != this.size(); i++)
{
values[i] = this.getObjectAt(i);
}
return values;
}
public ASN1SetParser parser()
{
final ASN1Set outer = this;
return new ASN1SetParser()
{
private final int max = size();
private int index;
public ASN1Encodable readObject() throws IOException
{
if (index == max)
{
return null;
}
ASN1Encodable obj = getObjectAt(index++);
if (obj instanceof ASN1Sequence)
{
return ((ASN1Sequence)obj).parser();
}
if (obj instanceof ASN1Set)
{
return ((ASN1Set)obj).parser();
}
return obj;
}
public ASN1Primitive getLoadedObject()
{
return outer;
}
public ASN1Primitive toASN1Primitive()
{
return outer;
}
};
}
public int hashCode()
{
Enumeration e = this.getObjects();
int hashCode = size();
while (e.hasMoreElements())
{
Object o = getNext(e);
hashCode *= 17;
hashCode ^= o.hashCode();
}
return hashCode;
}
/**
* Change current SET object to be encoded as {@link DERSet}.
* This is part of Distinguished Encoding Rules form serialization.
*/
ASN1Primitive toDERObject()
{
if (isSorted)
{
ASN1Set derSet = new DERSet();
derSet.set = this.set;
return derSet;
}
else
{
Vector v = new Vector();
for (int i = 0; i != set.size(); i++)
{
v.addElement(set.elementAt(i));
}
ASN1Set derSet = new DERSet();
derSet.set = v;
derSet.sort();
return derSet;
}
}
/**
* Change current SET object to be encoded as {@link DLSet}.
* This is part of Direct Length form serialization.
*/
ASN1Primitive toDLObject()
{
ASN1Set derSet = new DLSet();
derSet.set = this.set;
return derSet;
}
boolean asn1Equals(
ASN1Primitive 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())
{
ASN1Encodable obj1 = getNext(s1);
ASN1Encodable obj2 = getNext(s2);
ASN1Primitive o1 = obj1.toASN1Primitive();
ASN1Primitive o2 = obj2.toASN1Primitive();
if (o1 == o2 || o1.equals(o2))
{
continue;
}
return false;
}
return true;
}
private ASN1Encodable getNext(Enumeration e)
{
ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
// unfortunately null was allowed as a substitute for DER null
if (encObj == null)
{
return DERNull.INSTANCE;
}
return encObj;
}
/**
* return true if a <= b (arrays are assumed padded with zeros).
*/
private boolean lessThanOrEqual(
byte[] a,
byte[] b)
{
int len = Math.min(a.length, b.length);
for (int i = 0; i != len; ++i)
{
if (a[i] != b[i])
{
return (a[i] & 0xff) < (b[i] & 0xff);
}
}
return len == a.length;
}
private byte[] getEncoded(
ASN1Encodable 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 (!isSorted)
{
isSorted = true;
if (set.size() > 1)
{
boolean swapped = true;
int lastSwap = set.size() - 1;
while (swapped)
{
int index = 0;
int swapIndex = 0;
byte[] a = getEncoded((ASN1Encodable)set.elementAt(0));
swapped = false;
while (index != lastSwap)
{
byte[] b = getEncoded((ASN1Encodable)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;
}
}
}
}
boolean isConstructed()
{
return true;
}
abstract void encode(ASN1OutputStream out)
throws IOException;
public String toString()
{
return set.toString();
}
}

View File

@ -1,19 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
/**
* A basic parser for a SET object
*/
public interface ASN1SetParser
extends ASN1Encodable, InMemoryRepresentable
{
/**
* Read the next object from the underlying object representing a SET.
*
* @throws IOException for bad input stream.
* @return the next object, null if we are at the end.
*/
public ASN1Encodable readObject()
throws IOException;
}

View File

@ -1,250 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A parser for ASN.1 streams which also returns, where possible, parsers for the objects it encounters.
*/
public class ASN1StreamParser
{
private final InputStream _in;
private final int _limit;
private final byte[][] tmpBuffers;
public ASN1StreamParser(
InputStream in)
{
this(in, StreamUtil.findLimit(in));
}
public ASN1StreamParser(
InputStream in,
int limit)
{
this._in = in;
this._limit = limit;
this.tmpBuffers = new byte[11][];
}
public ASN1StreamParser(
byte[] encoding)
{
this(new ByteArrayInputStream(encoding), encoding.length);
}
ASN1Encodable readIndef(int tagValue) throws IOException
{
// Note: INDEF => CONSTRUCTED
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagValue)
{
case BERTags.EXTERNAL:
return new DERExternalParser(this);
case BERTags.OCTET_STRING:
return new BEROctetStringParser(this);
case BERTags.SEQUENCE:
return new BERSequenceParser(this);
case BERTags.SET:
return new BERSetParser(this);
default:
throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
}
}
ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
{
if (_in instanceof IndefiniteLengthInputStream)
{
if (!constructed)
{
throw new IOException("indefinite length primitive encoding encountered");
}
return readIndef(tag);
}
if (constructed)
{
switch (tag)
{
case BERTags.SET:
return new DERSetParser(this);
case BERTags.SEQUENCE:
return new DERSequenceParser(this);
case BERTags.OCTET_STRING:
return new BEROctetStringParser(this);
}
}
else
{
switch (tag)
{
case BERTags.SET:
throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
case BERTags.SEQUENCE:
throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
case BERTags.OCTET_STRING:
return new DEROctetStringParser((DefiniteLengthInputStream)_in);
}
}
// TODO ASN1Exception
throw new RuntimeException("implicit tagging not implemented");
}
ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
{
if (!constructed)
{
// Note: !CONSTRUCTED => IMPLICIT
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
}
ASN1EncodableVector v = readVector();
if (_in instanceof IndefiniteLengthInputStream)
{
return v.size() == 1
? new BERTaggedObject(true, tag, v.get(0))
: new BERTaggedObject(false, tag, BERFactory.createSequence(v));
}
return v.size() == 1
? new DERTaggedObject(true, tag, v.get(0))
: new DERTaggedObject(false, tag, DERFactory.createSequence(v));
}
public ASN1Encodable 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 & BERTags.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, _limit);
ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
if ((tag & BERTags.APPLICATION) != 0)
{
return new BERApplicationSpecificParser(tagNo, sp);
}
if ((tag & BERTags.TAGGED) != 0)
{
return new BERTaggedObjectParser(true, tagNo, sp);
}
return sp.readIndef(tagNo);
}
else
{
DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
if ((tag & BERTags.APPLICATION) != 0)
{
return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
}
if ((tag & BERTags.TAGGED) != 0)
{
return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
}
if (isConstructed)
{
// TODO There are other tags that may be constructed (e.g. BIT_STRING)
switch (tagNo)
{
case BERTags.OCTET_STRING:
//
// yes, people actually do this...
//
return new BEROctetStringParser(new ASN1StreamParser(defIn));
case BERTags.SEQUENCE:
return new DERSequenceParser(new ASN1StreamParser(defIn));
case BERTags.SET:
return new DERSetParser(new ASN1StreamParser(defIn));
case BERTags.EXTERNAL:
return new DERExternalParser(new ASN1StreamParser(defIn));
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
}
// Some primitive encodings can be handled by parsers too...
switch (tagNo)
{
case BERTags.OCTET_STRING:
return new DEROctetStringParser(defIn);
}
try
{
return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
}
catch (IllegalArgumentException e)
{
throw new ASN1Exception("corrupted stream detected", e);
}
}
}
private void set00Check(boolean enabled)
{
if (_in instanceof IndefiniteLengthInputStream)
{
((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
}
}
ASN1EncodableVector readVector() throws IOException
{
ASN1EncodableVector v = new ASN1EncodableVector();
ASN1Encodable obj;
while ((obj = readObject()) != null)
{
if (obj instanceof InMemoryRepresentable)
{
v.add(((InMemoryRepresentable)obj).getLoadedObject());
}
else
{
v.add(obj.toASN1Primitive());
}
}
return v;
}
}

View File

@ -1,6 +0,0 @@
package org.spongycastle.asn1;
public interface ASN1String
{
public String getString();
}

View File

@ -1,236 +0,0 @@
package org.spongycastle.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 ASN1Primitive
implements ASN1TaggedObjectParser
{
int tagNo;
boolean empty = false;
boolean explicit = true;
ASN1Encodable 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;
}
else if (obj instanceof byte[])
{
try
{
return ASN1TaggedObject.getInstance(fromByteArray((byte[])obj));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct tagged object from byte[]: " + e.getMessage());
}
}
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
}
/**
* Create a tagged object with the style given by the value of explicit.
* <p>
* If the object implements ASN1Choice the tag style will always be changed
* to explicit in accordance with the ASN.1 encoding rules.
* </p>
* @param explicit true if the object is explicitly tagged.
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public ASN1TaggedObject(
boolean explicit,
int tagNo,
ASN1Encodable obj)
{
if (obj instanceof ASN1Choice)
{
this.explicit = true;
}
else
{
this.explicit = explicit;
}
this.tagNo = tagNo;
if (this.explicit)
{
this.obj = obj;
}
else
{
ASN1Primitive prim = obj.toASN1Primitive();
if (prim instanceof ASN1Set)
{
ASN1Set s = null;
}
this.obj = obj;
}
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1TaggedObject))
{
return false;
}
ASN1TaggedObject other = (ASN1TaggedObject)o;
if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
{
return false;
}
if(obj == null)
{
if (other.obj != null)
{
return false;
}
}
else
{
if (!(obj.toASN1Primitive().equals(other.obj.toASN1Primitive())))
{
return false;
}
}
return true;
}
public int hashCode()
{
int code = tagNo;
// TODO: actually this is wrong - the problem is that a re-encoded
// object may end up with a different hashCode due to implicit
// tagging. As implicit tagging is ambiguous if a sequence is involved
// it seems the only correct method for both equals and hashCode is to
// compare the encodings...
if (obj != null)
{
code ^= obj.hashCode();
}
return code;
}
public int getTagNo()
{
return tagNo;
}
/**
* return whether or not the object may be explicitly tagged.
* <p>
* 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.
* <p>
* 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 ASN1Primitive getObject()
{
if (obj != null)
{
return obj.toASN1Primitive();
}
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 ASN1Encodable getObjectParser(
int tag,
boolean isExplicit)
{
switch (tag)
{
case BERTags.SET:
return ASN1Set.getInstance(this, isExplicit).parser();
case BERTags.SEQUENCE:
return ASN1Sequence.getInstance(this, isExplicit).parser();
case BERTags.OCTET_STRING:
return ASN1OctetString.getInstance(this, isExplicit).parser();
}
if (isExplicit)
{
return getObject();
}
throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
}
public ASN1Primitive getLoadedObject()
{
return this.toASN1Primitive();
}
ASN1Primitive toDERObject()
{
return new DERTaggedObject(explicit, tagNo, obj);
}
ASN1Primitive toDLObject()
{
return new DLTaggedObject(explicit, tagNo, obj);
}
abstract void encode(ASN1OutputStream out)
throws IOException;
public String toString()
{
return "[" + tagNo + "]" + obj;
}
}

View File

@ -1,12 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
public interface ASN1TaggedObjectParser
extends ASN1Encodable, InMemoryRepresentable
{
public int getTagNo();
public ASN1Encodable getObjectParser(int tag, boolean isExplicit)
throws IOException;
}

View File

@ -1,314 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.Strings;
/**
- * UTC time object.
* Internal facade of {@link ASN1UTCTime}.
* <p>
* This datatype is valid only from 1950-01-01 00:00:00 UTC until 2049-12-31 23:59:59 UTC.
* <p>
* <hr>
* <p><b>X.690</b></p>
* <p><b>11: Restrictions on BER employed by both CER and DER</b></p>
* <p><b>11.8 UTCTime </b></p>
* <b>11.8.1</b> The encoding shall terminate with "Z",
* as described in the ITU-T X.680 | ISO/IEC 8824-1 clause on UTCTime.
* <p>
* <b>11.8.2</b> The seconds element shall always be present.
* <p>
* <b>11.8.3</b> Midnight (GMT) shall be represented in the form:
* <blockquote>
* "YYMMDD000000Z"
* </blockquote>
* where "YYMMDD" represents the day following the midnight in question.
*/
public class ASN1UTCTime
extends ASN1Primitive
{
private byte[] time;
/**
* return an UTC Time from the passed in object.
*
* @param obj an ASN1UTCTime or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
* @return an ASN1UTCTime instance, or null.
*/
public static ASN1UTCTime getInstance(
Object obj)
{
if (obj == null || obj instanceof ASN1UTCTime)
{
return (ASN1UTCTime)obj;
}
if (obj instanceof byte[])
{
try
{
return (ASN1UTCTime)fromByteArray((byte[])obj);
}
catch (Exception e)
{
throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return an UTC Time from a tagged object.
*
* @param obj the tagged object holding the object we want
* @param explicit true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException if the tagged object cannot
* be converted.
* @return an ASN1UTCTime instance, or null.
*/
public static ASN1UTCTime getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Object o = obj.getObject();
if (explicit || o instanceof ASN1UTCTime)
{
return getInstance(o);
}
else
{
return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
}
}
/**
* The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
* never encoded. When you're creating one of these objects from scratch, that's
* what you want to use, otherwise we'll try to deal with whatever gets read from
* the input stream... (this is why the input format is different from the getTime()
* method output).
* <p>
*
* @param time the time string.
*/
public ASN1UTCTime(
String time)
{
this.time = Strings.toByteArray(time);
try
{
this.getDate();
}
catch (ParseException e)
{
throw new IllegalArgumentException("invalid date string: " + e.getMessage());
}
}
/**
* base constructor from a java.util.date object
* @param time the Date to build the time from.
*/
public ASN1UTCTime(
Date time)
{
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
this.time = Strings.toByteArray(dateF.format(time));
}
/**
* Base constructor from a java.util.date and Locale - you may need to use this if the default locale
* doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
*
* @param time a date object representing the time of interest.
* @param locale an appropriate Locale for producing an ASN.1 UTCTime value.
*/
public ASN1UTCTime(
Date time,
Locale locale)
{
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'", locale);
dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
this.time = Strings.toByteArray(dateF.format(time));
}
ASN1UTCTime(
byte[] time)
{
this.time = time;
}
/**
* return the time as a date based on whatever a 2 digit year will return. For
* standardised processing use getAdjustedDate().
*
* @return the resulting date
* @exception ParseException if the date string cannot be parsed.
*/
public Date getDate()
throws ParseException
{
SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
return dateF.parse(getTime());
}
/**
* return the time as an adjusted date
* in the range of 1950 - 2049.
*
* @return a date in the range of 1950 to 2049.
* @exception ParseException if the date string cannot be parsed.
*/
public Date getAdjustedDate()
throws ParseException
{
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
return dateF.parse(getAdjustedTime());
}
/**
* return the time - always in the form of
* YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
* <p>
* Normally in a certificate we would expect "Z" rather than "GMT",
* however adding the "GMT" means we can just use:
* <pre>
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
* </pre>
* To read in the time and get a date which is compatible with our local
* time zone.
* <p>
* <b>Note:</b> In some cases, due to the local date processing, this
* may lead to unexpected results. If you want to stick the normal
* convention of 1950 to 2049 use the getAdjustedTime() method.
*/
public String getTime()
{
String stime = Strings.fromByteArray(time);
//
// standardise the format.
//
if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
{
if (stime.length() == 11)
{
return stime.substring(0, 10) + "00GMT+00:00";
}
else
{
return stime.substring(0, 12) + "GMT+00:00";
}
}
else
{
int index = stime.indexOf('-');
if (index < 0)
{
index = stime.indexOf('+');
}
String d = stime;
if (index == stime.length() - 3)
{
d += "00";
}
if (index == 10)
{
return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
}
else
{
return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
}
}
}
/**
* return a time string as an adjusted date with a 4 digit year. This goes
* in the range of 1950 - 2049.
*/
public String getAdjustedTime()
{
String d = this.getTime();
if (d.charAt(0) < '5')
{
return "20" + d;
}
else
{
return "19" + d;
}
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
int length = time.length;
return 1 + StreamUtil.calculateBodyLength(length) + length;
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.UTC_TIME);
int length = time.length;
out.writeLength(length);
for (int i = 0; i != length; i++)
{
out.write((byte)time[i]);
}
}
boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof ASN1UTCTime))
{
return false;
}
return Arrays.areEqual(time, ((ASN1UTCTime)o).time);
}
public int hashCode()
{
return Arrays.hashCode(time);
}
public String toString()
{
return Strings.fromByteArray(time);
}
}

View File

@ -1,10 +0,0 @@
package org.spongycastle.asn1;
public class BERApplicationSpecific
extends DERApplicationSpecific
{
public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
{
super(tagNo, vec);
}
}

View File

@ -1,41 +0,0 @@
package org.spongycastle.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 ASN1Encodable readObject()
throws IOException
{
return parser.readObject();
}
public ASN1Primitive getLoadedObject()
throws IOException
{
return new BERApplicationSpecific(tag, parser.readVector());
}
public ASN1Primitive toASN1Primitive()
{
try
{
return getLoadedObject();
}
catch (IOException e)
{
throw new ASN1ParsingException(e.getMessage(), e);
}
}
}

View File

@ -1,144 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
/**
* @deprecated use BEROctetString
*/
public class BERConstructedOctetString
extends BEROctetString
{
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(
ASN1Primitive obj)
{
super(toByteArray(obj));
}
private static byte[] toByteArray(ASN1Primitive obj)
{
try
{
return obj.getEncoded();
}
catch (IOException e)
{
throw new IllegalArgumentException("Unable to encode object");
}
}
public BERConstructedOctetString(
ASN1Encodable obj)
{
this(obj.toASN1Primitive());
}
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 static BEROctetString fromSequence(ASN1Sequence seq)
{
Vector v = new Vector();
Enumeration e = seq.getObjects();
while (e.hasMoreElements())
{
v.addElement(e.nextElement());
}
return new BERConstructedOctetString(v);
}
}

View File

@ -1,17 +0,0 @@
package org.spongycastle.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);
}
}

View File

@ -1,100 +0,0 @@
package org.spongycastle.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 | BERTags.TAGGED;
if (_isExplicit)
{
writeHdr(tagNum | BERTags.CONSTRUCTED);
writeHdr(tag);
}
else
{
if ((tag & BERTags.CONSTRUCTED) != 0)
{
writeHdr(tagNum | BERTags.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);
}
}
}

View File

@ -1,168 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
public class BEROctetString
extends ASN1OctetString
{
private static final int MAX_LENGTH = 1000;
private ASN1OctetString[] octs;
/**
* convert a vector of octet strings into a single byte string
*/
static private byte[] toBytes(
ASN1OctetString[] octs)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
for (int i = 0; i != octs.length; i++)
{
try
{
DEROctetString o = (DEROctetString)octs[i];
bOut.write(o.getOctets());
}
catch (ClassCastException e)
{
throw new IllegalArgumentException(octs[i].getClass().getName() + " found in input should only contain DEROctetString");
}
catch (IOException e)
{
throw new IllegalArgumentException("exception converting octets " + e.toString());
}
}
return bOut.toByteArray();
}
/**
* @param string the octets making up the octet string.
*/
public BEROctetString(
byte[] string)
{
super(string);
}
public BEROctetString(
ASN1OctetString[] octs)
{
super(toBytes(octs));
this.octs = octs;
}
public byte[] getOctets()
{
return string;
}
/**
* return the DER octets that make up this string.
*/
public Enumeration getObjects()
{
if (octs == null)
{
return generateOcts().elements();
}
return new Enumeration()
{
int counter = 0;
public boolean hasMoreElements()
{
return counter < octs.length;
}
public Object nextElement()
{
return octs[counter++];
}
};
}
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;
}
boolean isConstructed()
{
return true;
}
int encodedLength()
throws IOException
{
int length = 0;
for (Enumeration e = getObjects(); e.hasMoreElements();)
{
length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
}
return 2 + length + 2;
}
public void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
out.write(0x80);
//
// write out the octet array
//
for (Enumeration e = getObjects(); e.hasMoreElements();)
{
out.writeObject((ASN1Encodable)e.nextElement());
}
out.write(0x00);
out.write(0x00);
}
static BEROctetString fromSequence(ASN1Sequence seq)
{
ASN1OctetString[] v = new ASN1OctetString[seq.size()];
Enumeration e = seq.getObjects();
int index = 0;
while (e.hasMoreElements())
{
v[index++] = (ASN1OctetString)e.nextElement();
}
return new BEROctetString(v);
}
}

View File

@ -1,102 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.io.OutputStream;
public class BEROctetStringGenerator
extends BERGenerator
{
public BEROctetStringGenerator(OutputStream out)
throws IOException
{
super(out);
writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
}
public BEROctetStringGenerator(
OutputStream out,
int tagNo,
boolean isExplicit)
throws IOException
{
super(out, tagNo, isExplicit);
writeBERHeader(BERTags.CONSTRUCTED | BERTags.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();
}
}
}

View File

@ -1,41 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.io.InputStream;
import org.spongycastle.util.io.Streams;
public class BEROctetStringParser
implements ASN1OctetStringParser
{
private ASN1StreamParser _parser;
BEROctetStringParser(
ASN1StreamParser parser)
{
_parser = parser;
}
public InputStream getOctetStream()
{
return new ConstructedOctetStream(_parser);
}
public ASN1Primitive getLoadedObject()
throws IOException
{
return new BEROctetString(Streams.readAll(getOctetStream()));
}
public ASN1Primitive toASN1Primitive()
{
try
{
return getLoadedObject();
}
catch (IOException e)
{
throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
}
}
}

View File

@ -1,36 +0,0 @@
package org.spongycastle.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 ASN1Primitive)
{
((ASN1Primitive)obj).encode(this);
}
else if (obj instanceof ASN1Encodable)
{
((ASN1Encodable)obj).toASN1Primitive().encode(this);
}
else
{
throw new IOException("object not BEREncodable");
}
}
}

View File

@ -1,73 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
public class BERSequence
extends ASN1Sequence
{
/**
* create an empty sequence
*/
public BERSequence()
{
}
/**
* create a sequence containing one object
*/
public BERSequence(
ASN1Encodable obj)
{
super(obj);
}
/**
* create a sequence containing a vector of objects.
*/
public BERSequence(
ASN1EncodableVector v)
{
super(v);
}
/**
* create a sequence containing an array of objects.
*/
public BERSequence(
ASN1Encodable[] array)
{
super(array);
}
int encodedLength()
throws IOException
{
int length = 0;
for (Enumeration e = getObjects(); e.hasMoreElements();)
{
length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
}
return 2 + length + 2;
}
/*
*/
void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
out.write(0x80);
Enumeration e = getObjects();
while (e.hasMoreElements())
{
out.writeObject((ASN1Encodable)e.nextElement());
}
out.write(0x00);
out.write(0x00);
}
}

View File

@ -1,41 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.io.OutputStream;
public class BERSequenceGenerator
extends BERGenerator
{
public BERSequenceGenerator(
OutputStream out)
throws IOException
{
super(out);
writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
}
public BERSequenceGenerator(
OutputStream out,
int tagNo,
boolean isExplicit)
throws IOException
{
super(out, tagNo, isExplicit);
writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
}
public void addObject(
ASN1Encodable object)
throws IOException
{
object.toASN1Primitive().encode(new BEROutputStream(_out));
}
public void close()
throws IOException
{
writeBEREnd();
}
}

View File

@ -1,38 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
public class BERSequenceParser
implements ASN1SequenceParser
{
private ASN1StreamParser _parser;
BERSequenceParser(ASN1StreamParser parser)
{
this._parser = parser;
}
public ASN1Encodable readObject()
throws IOException
{
return _parser.readObject();
}
public ASN1Primitive getLoadedObject()
throws IOException
{
return new BERSequence(_parser.readVector());
}
public ASN1Primitive toASN1Primitive()
{
try
{
return getLoadedObject();
}
catch (IOException e)
{
throw new IllegalStateException(e.getMessage());
}
}
}

View File

@ -1,73 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.util.Enumeration;
public class BERSet
extends ASN1Set
{
/**
* create an empty sequence
*/
public BERSet()
{
}
/**
* @param obj - a single object that makes up the set.
*/
public BERSet(
ASN1Encodable obj)
{
super(obj);
}
/**
* @param v - a vector of objects making up the set.
*/
public BERSet(
ASN1EncodableVector v)
{
super(v, false);
}
/**
* create a set from an array of objects.
*/
public BERSet(
ASN1Encodable[] a)
{
super(a, false);
}
int encodedLength()
throws IOException
{
int length = 0;
for (Enumeration e = getObjects(); e.hasMoreElements();)
{
length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
}
return 2 + length + 2;
}
/*
*/
void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.SET | BERTags.CONSTRUCTED);
out.write(0x80);
Enumeration e = getObjects();
while (e.hasMoreElements())
{
out.writeObject((ASN1Encodable)e.nextElement());
}
out.write(0x00);
out.write(0x00);
}
}

View File

@ -1,38 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
public class BERSetParser
implements ASN1SetParser
{
private ASN1StreamParser _parser;
BERSetParser(ASN1StreamParser parser)
{
this._parser = parser;
}
public ASN1Encodable readObject()
throws IOException
{
return _parser.readObject();
}
public ASN1Primitive getLoadedObject()
throws IOException
{
return new BERSet(_parser.readVector());
}
public ASN1Primitive toASN1Primitive()
{
try
{
return getLoadedObject();
}
catch (IOException e)
{
throw new ASN1ParsingException(e.getMessage(), e);
}
}
}

View File

@ -1,147 +0,0 @@
package org.spongycastle.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).
*/
public class BERTaggedObject
extends ASN1TaggedObject
{
/**
* @param tagNo the tag number for this object.
* @param obj the tagged object.
*/
public BERTaggedObject(
int tagNo,
ASN1Encodable obj)
{
super(true, 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,
ASN1Encodable 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());
}
boolean isConstructed()
{
if (!empty)
{
if (explicit)
{
return true;
}
else
{
ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
return primitive.isConstructed();
}
}
else
{
return true;
}
}
int encodedLength()
throws IOException
{
if (!empty)
{
ASN1Primitive primitive = obj.toASN1Primitive();
int length = primitive.encodedLength();
if (explicit)
{
return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
}
else
{
// header length already in calculation
length = length - 1;
return StreamUtil.calculateTagLength(tagNo) + length;
}
}
else
{
return StreamUtil.calculateTagLength(tagNo) + 1;
}
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
out.write(0x80);
if (!empty)
{
if (!explicit)
{
Enumeration e;
if (obj instanceof ASN1OctetString)
{
if (obj instanceof BEROctetString)
{
e = ((BEROctetString)obj).getObjects();
}
else
{
ASN1OctetString octs = (ASN1OctetString)obj;
BEROctetString berO = new BEROctetString(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((ASN1Encodable)e.nextElement());
}
}
else
{
out.writeObject(obj);
}
}
out.write(0x00);
out.write(0x00);
}
}

View File

@ -1,66 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
public class BERTaggedObjectParser
implements ASN1TaggedObjectParser
{
private boolean _constructed;
private int _tagNumber;
private ASN1StreamParser _parser;
BERTaggedObjectParser(
boolean constructed,
int tagNumber,
ASN1StreamParser parser)
{
_constructed = constructed;
_tagNumber = tagNumber;
_parser = parser;
}
public boolean isConstructed()
{
return _constructed;
}
public int getTagNo()
{
return _tagNumber;
}
public ASN1Encodable getObjectParser(
int tag,
boolean isExplicit)
throws IOException
{
if (isExplicit)
{
if (!_constructed)
{
throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
}
return _parser.readObject();
}
return _parser.readImplicit(_constructed, tag);
}
public ASN1Primitive getLoadedObject()
throws IOException
{
return _parser.readTaggedObject(_constructed, _tagNumber);
}
public ASN1Primitive toASN1Primitive()
{
try
{
return this.getLoadedObject();
}
catch (IOException e)
{
throw new ASN1ParsingException(e.getMessage());
}
}
}

View File

@ -1,36 +0,0 @@
package org.spongycastle.asn1;
public interface BERTags
{
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 - used to model a SEQUENCE of the same type.
public static final int SET = 0x11;
public static final int SET_OF = 0x11; // for completeness - used to model a SET of the same type.
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;
}

View File

@ -1,111 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import java.io.InputStream;
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();
}
}
}

View File

@ -1,267 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.spongycastle.util.Arrays;
/**
* Base class for an application specific object
*/
public class DERApplicationSpecific
extends ASN1Primitive
{
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,
ASN1Encodable object)
throws IOException
{
this(true, tag, object);
}
public DERApplicationSpecific(
boolean explicit,
int tag,
ASN1Encodable object)
throws IOException
{
ASN1Primitive primitive = object.toASN1Primitive();
byte[] data = primitive.getEncoded(ASN1Encoding.DER);
this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
this.tag = tag;
if (explicit)
{
this.octets = data;
}
else
{
int lenBytes = getLengthOfHeader(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(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
}
catch (IOException e)
{
throw new ASN1ParsingException("malformed object: " + e, e);
}
}
this.octets = bOut.toByteArray();
}
public static DERApplicationSpecific getInstance(Object obj)
{
if (obj == null || obj instanceof DERApplicationSpecific)
{
return (DERApplicationSpecific)obj;
}
else if (obj instanceof byte[])
{
try
{
return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
}
catch (IOException e)
{
throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
}
}
throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
}
private int getLengthOfHeader(byte[] data)
{
int length = data[1] & 0xff; // TODO: assumes 1 byte tag
if (length == 0x80)
{
return 2; // indefinite-length encoding
}
if (length > 127)
{
int size = length & 0x7f;
// Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
if (size > 4)
{
throw new IllegalStateException("DER length more than 4 bytes: " + size);
}
return size + 2;
}
return 2;
}
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 ASN1Primitive 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 ASN1Primitive 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] & BERTags.CONSTRUCTED) != 0)
{
tmp[0] |= BERTags.CONSTRUCTED;
}
return new ASN1InputStream(tmp).readObject();
}
int encodedLength()
throws IOException
{
return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
}
/* (non-Javadoc)
* @see org.spongycastle.asn1.ASN1Primitive#encode(org.spongycastle.asn1.DEROutputStream)
*/
void encode(ASN1OutputStream out) throws IOException
{
int classBits = BERTags.APPLICATION;
if (isConstructed)
{
classBits |= BERTags.CONSTRUCTED;
}
out.writeEncoded(classBits, tag, octets);
}
boolean asn1Equals(
ASN1Primitive 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;
}
}

View File

@ -1,157 +0,0 @@
package org.spongycastle.asn1;
import java.io.IOException;
import org.spongycastle.util.Arrays;
/**
* DER BMPString object.
*/
public class DERBMPString
extends ASN1Primitive
implements ASN1String
{
private char[] string;
/**
* return a BMP String from the given object.
*
* @param obj the object we want converted.
* @exception IllegalArgumentException if the object cannot be converted.
* @return a DERBMPString instance, or null.
*/
public static DERBMPString getInstance(
Object obj)
{
if (obj == null || obj instanceof DERBMPString)
{
return (DERBMPString)obj;
}
if (obj instanceof byte[])
{
try
{
return (DERBMPString)fromByteArray((byte[])obj);
}
catch (Exception e)
{
throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
}
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return 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.
* @return a DERBMPString instance.
*/
public static DERBMPString getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof DERBMPString)
{
return getInstance(o);
}
else
{
return new DERBMPString(ASN1OctetString.getInstance(o).getOctets());
}
}
/**
* basic constructor - byte encoded string.
* @param string the encoded BMP STRING to wrap.
*/
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 = cs;
}
DERBMPString(char[] string)
{
this.string = string;
}
/**
* basic constructor
* @param string a String to wrap as a BMP STRING.
*/
public DERBMPString(
String string)
{
this.string = string.toCharArray();
}
public String getString()
{
return new String(string);
}
public String toString()
{
return getString();
}
public int hashCode()
{
return Arrays.hashCode(string);
}
protected boolean asn1Equals(
ASN1Primitive o)
{
if (!(o instanceof DERBMPString))
{
return false;
}
DERBMPString s = (DERBMPString)o;
return Arrays.areEqual(string, s.string);
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
return 1 + StreamUtil.calculateBodyLength(string.length * 2) + (string.length * 2);
}
void encode(
ASN1OutputStream out)
throws IOException
{
out.write(BERTags.BMP_STRING);
out.writeLength(string.length * 2);
for (int i = 0; i != string.length; i++)
{
char c = string[i];
out.write((byte)(c >> 8));
out.write((byte)c);
}
}
}

View File

@ -1,318 +0,0 @@
package org.spongycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import org.spongycastle.util.Arrays;
import org.spongycastle.util.io.Streams;
public class DERBitString
extends ASN1Primitive
implements ASN1String
{
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;
/**
* @param bitString an int containing the BIT STRING
* @return the correct number of pad bits for a bit string defined in
* a 32 bit constant
*/
static protected int getPadBits(
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;
}
/**
* @param bitString an int containing the BIT STRING
* @return the correct number of bytes for a bit string defined in
* a 32 bit constant
*/
static protected byte[] getBytes(int bitString)
{
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
*
* @param obj a DERBitString or an object that can be converted into one.
* @exception IllegalArgumentException if the object cannot be converted.
* @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(
Object obj)
{
if (obj == null || obj instanceof DERBitString)
{
return (DERBitString)obj;
}
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.
* @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(
ASN1TaggedObject obj,
boolean explicit)
{
ASN1Primitive o = obj.getObject();
if (explicit || o instanceof DERBitString)
{
return getInstance(o);
}
else
{
return fromOctetString(((ASN1OctetString)o).getOctets());
}
}
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(
int value)
{
this.data = getBytes(value);
this.padBits = getPadBits(value);
}
public DERBitString(
ASN1Encodable obj)
throws IOException
{
this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
this.padBits = 0;
}
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;
}
boolean isConstructed()
{
return false;
}
int encodedLength()
{
return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
}
void encode(
ASN1OutputStream 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(BERTags.BIT_STRING, bytes);
}
public int hashCode()
{
return padBits ^ Arrays.hashCode(data);
}
protected boolean asn1Equals(
ASN1Primitive 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();
}
static DERBitString fromOctetString(byte[] bytes)
{
if (bytes.length < 1)
{
throw new IllegalArgumentException("truncated BIT STRING detected");
}
int padBits = bytes[0];
byte[] data = new byte[bytes.length - 1];
if (data.length != 0)
{
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
}
return new DERBitString(data, padBits);
}
static DERBitString fromInputStream(int length, InputStream stream)
throws IOException
{
if (length < 1)
{
throw new IllegalArgumentException("truncated BIT STRING detected");
}
int padBits = stream.read();
byte[] data = new byte[length - 1];
if (data.length != 0)
{
if (Streams.readFully(stream, data) != data.length)
{
throw new EOFException("EOF encountered in middle of BIT STRING");
}
}
return new DERBitString(data, padBits);
}
}

View File

@ -1,22 +0,0 @@
package org.spongycastle.asn1;
/**
* @deprecated use ASN1Boolean
*/
public class DERBoolean
extends ASN1Boolean
{
/**
* @deprecated use getInstance(boolean) method.
* @param value
*/
public DERBoolean(boolean value)
{
super(value);
}
DERBoolean(byte[] value)
{
super(value);
}
}

Some files were not shown because too many files have changed in this diff Show More