Browse Source
Merge in CORE/base-third from ~CLOUD.LIU/base-third:feature/x to feature/x * commit '633a29cc976409da95356f5abfbfb3651a41cf70': KERNEL-12978 feat: 用户登录权限CBBfeature/x
Cloud.Liu-刘学真
2 years ago
3627 changed files with 7 additions and 807733 deletions
@ -1,6 +0,0 @@
|
||||
*.iml |
||||
.idea/ |
||||
.DS_Store |
||||
.project |
||||
.classpath |
||||
*.gradle |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<parent> |
||||
<groupId>com.fr.third</groupId> |
||||
<artifactId>step1</artifactId> |
||||
<version>${revision}</version> |
||||
<relativePath>../base-third-project/base-third-step1</relativePath> |
||||
</parent> |
||||
|
||||
<artifactId>fine-bouncycastle</artifactId> |
||||
<version>${revision}</version> |
||||
|
||||
|
||||
</project> |
@ -1,2 +0,0 @@
|
||||
版本:1.68<br> |
||||
源码:https://www.bouncycastle.org/latest_releases.html<br> |
@ -1,65 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* The Bouncy Castle License |
||||
* |
||||
* Copyright (c) 2000-2021 The Legion Of The Bouncy Castle Inc. (https://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 final String licenseText = |
||||
"Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) " |
||||
+ Strings.lineSeparator() |
||||
+ Strings.lineSeparator() |
||||
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software " |
||||
+ Strings.lineSeparator() |
||||
+ "and associated documentation files (the \"Software\"), to deal in the Software without restriction, " |
||||
+ Strings.lineSeparator() |
||||
+ "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, " |
||||
+ Strings.lineSeparator() |
||||
+ "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so," |
||||
+ Strings.lineSeparator() |
||||
+ "subject to the following conditions:" |
||||
+ Strings.lineSeparator() |
||||
+ Strings.lineSeparator() |
||||
+ "The above copyright notice and this permission notice shall be included in all copies or substantial" |
||||
+ Strings.lineSeparator() |
||||
+ "portions of the Software." |
||||
+ Strings.lineSeparator() |
||||
+ Strings.lineSeparator() |
||||
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED," |
||||
+ Strings.lineSeparator() |
||||
+ "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR" |
||||
+ Strings.lineSeparator() |
||||
+ "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE" |
||||
+ Strings.lineSeparator() |
||||
+ "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR" |
||||
+ Strings.lineSeparator() |
||||
+ "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER" |
||||
+ Strings.lineSeparator() |
||||
+ "DEALINGS IN THE SOFTWARE."; |
||||
|
||||
public static void main( |
||||
String[] args) |
||||
{ |
||||
System.out.println(licenseText); |
||||
} |
||||
} |
@ -1,246 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.encoders.Hex; |
||||
|
||||
/** |
||||
* Base class for an ASN.1 ApplicationSpecific object |
||||
*/ |
||||
public abstract class ASN1ApplicationSpecific |
||||
extends ASN1Primitive |
||||
{ |
||||
protected final boolean isConstructed; |
||||
protected final int tag; |
||||
protected final byte[] octets; |
||||
|
||||
ASN1ApplicationSpecific( |
||||
boolean isConstructed, |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
this.isConstructed = isConstructed; |
||||
this.tag = tag; |
||||
this.octets = Arrays.clone(octets); |
||||
} |
||||
|
||||
/** |
||||
* Return an ASN1ApplicationSpecific from the passed in object, which may be a byte array, or null. |
||||
* |
||||
* @param obj the object to be converted. |
||||
* @return obj's representation as an ASN1ApplicationSpecific object. |
||||
*/ |
||||
public static ASN1ApplicationSpecific getInstance(Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof ASN1ApplicationSpecific) |
||||
{ |
||||
return (ASN1ApplicationSpecific)obj; |
||||
} |
||||
else if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return ASN1ApplicationSpecific.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()); |
||||
} |
||||
|
||||
protected static 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; |
||||
} |
||||
|
||||
/** |
||||
* Return true if the object is marked as constructed, false otherwise. |
||||
* |
||||
* @return true if constructed, otherwise false. |
||||
*/ |
||||
public boolean isConstructed() |
||||
{ |
||||
return isConstructed; |
||||
} |
||||
|
||||
/** |
||||
* Return the contents of this object as a byte[] |
||||
* |
||||
* @return the encoded contents of the object. |
||||
*/ |
||||
public byte[] getContents() |
||||
{ |
||||
return Arrays.clone(octets); |
||||
} |
||||
|
||||
/** |
||||
* Return the tag number associated with this object, |
||||
* |
||||
* @return the application tag number. |
||||
*/ |
||||
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 ASN1Primitive.fromByteArray(getContents()); |
||||
} |
||||
|
||||
/** |
||||
* 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 ASN1Primitive.fromByteArray(tmp); |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
int flags = BERTags.APPLICATION; |
||||
if (isConstructed) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeEncoded(withTag, flags, tag, octets); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof ASN1ApplicationSpecific)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1ApplicationSpecific other = (ASN1ApplicationSpecific)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) |
||||
{ |
||||
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 IOException("corrupted stream - invalid high tag number found"); |
||||
} |
||||
|
||||
while ((b & 0x80) != 0) |
||||
{ |
||||
b = input[index++] & 0xff; |
||||
} |
||||
} |
||||
|
||||
byte[] tmp = new byte[input.length - index + 1]; |
||||
|
||||
System.arraycopy(input, index, tmp, 1, tmp.length - 1); |
||||
|
||||
tmp[0] = (byte)newTag; |
||||
|
||||
return tmp; |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
StringBuffer sb = new StringBuffer(); |
||||
sb.append("["); |
||||
if (isConstructed()) |
||||
{ |
||||
sb.append("CONSTRUCTED "); |
||||
} |
||||
sb.append("APPLICATION "); |
||||
sb.append(Integer.toString(getApplicationTag())); |
||||
sb.append("]"); |
||||
// @todo content encoding somehow?
|
||||
if (this.octets != null) |
||||
{ |
||||
sb.append(" #"); |
||||
sb.append(Hex.toHexString(this.octets)); |
||||
} |
||||
else |
||||
{ |
||||
sb.append(" #null"); |
||||
} |
||||
sb.append(" "); |
||||
return sb.toString(); |
||||
} |
||||
} |
@ -1,19 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Interface to parse ASN.1 ApplicationSpecific 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; |
||||
} |
@ -1,326 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.EOFException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.io.Streams; |
||||
|
||||
/** |
||||
* Base class for BIT STRING objects |
||||
*/ |
||||
public abstract class ASN1BitString |
||||
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 final byte[] data; |
||||
protected final 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 0; |
||||
} |
||||
|
||||
|
||||
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) |
||||
{ |
||||
if (bitString == 0) |
||||
{ |
||||
return new byte[0]; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
protected ASN1BitString(byte data, int padBits) |
||||
{ |
||||
if (padBits > 7 || padBits < 0) |
||||
{ |
||||
throw new IllegalArgumentException("pad bits cannot be greater than 7 or less than 0"); |
||||
} |
||||
|
||||
this.data = new byte[]{ data }; |
||||
this.padBits = padBits; |
||||
} |
||||
|
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @param data the octets making up the bit string. |
||||
* @param padBits the number of extra bits at the end of the string. |
||||
*/ |
||||
public ASN1BitString( |
||||
byte[] data, |
||||
int padBits) |
||||
{ |
||||
if (data == null) |
||||
{ |
||||
throw new NullPointerException("'data' cannot be null"); |
||||
} |
||||
if (data.length == 0 && padBits != 0) |
||||
{ |
||||
throw new IllegalArgumentException("zero length data with non-zero pad bits"); |
||||
} |
||||
if (padBits > 7 || padBits < 0) |
||||
{ |
||||
throw new IllegalArgumentException("pad bits cannot be greater than 7 or less than 0"); |
||||
} |
||||
|
||||
this.data = Arrays.clone(data); |
||||
this.padBits = padBits; |
||||
} |
||||
|
||||
/** |
||||
* Return a String representation of this BIT STRING |
||||
* |
||||
* @return a String representation. |
||||
*/ |
||||
public String getString() |
||||
{ |
||||
StringBuffer buf = new StringBuffer("#"); |
||||
|
||||
byte[] string; |
||||
try |
||||
{ |
||||
string = getEncoded(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("Internal error encoding BitString: " + e.getMessage(), e); |
||||
} |
||||
|
||||
for (int i = 0; i != string.length; i++) |
||||
{ |
||||
buf.append(table[(string[i] >>> 4) & 0xf]); |
||||
buf.append(table[string[i] & 0xf]); |
||||
} |
||||
|
||||
return buf.toString(); |
||||
} |
||||
|
||||
/** |
||||
* @return the value of the bit string as an int (truncating if necessary) |
||||
*/ |
||||
public int intValue() |
||||
{ |
||||
int value = 0; |
||||
int end = Math.min(4, data.length - 1); |
||||
for (int i = 0; i < end; ++i) |
||||
{ |
||||
value |= (data[i] & 0xFF) << (8 * i); |
||||
} |
||||
if (0 <= end && end < 4) |
||||
{ |
||||
byte der = (byte)(data[end] & (0xFF << padBits)); |
||||
value |= (der & 0xFF) << (8 * end); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Return the octets contained in this BIT STRING, checking that this BIT STRING really |
||||
* does represent an octet aligned string. Only use this method when the standard you are |
||||
* following dictates that the BIT STRING will be octet aligned. |
||||
* |
||||
* @return a copy of the octet aligned data. |
||||
*/ |
||||
public byte[] getOctets() |
||||
{ |
||||
if (padBits != 0) |
||||
{ |
||||
throw new IllegalStateException("attempt to get non-octet aligned data from BIT STRING"); |
||||
} |
||||
|
||||
return Arrays.clone(data); |
||||
} |
||||
|
||||
public byte[] getBytes() |
||||
{ |
||||
if (0 == data.length) |
||||
{ |
||||
return data; |
||||
} |
||||
|
||||
byte[] rv = Arrays.clone(data); |
||||
// DER requires pad bits be zero
|
||||
rv[data.length - 1] &= (0xFF << padBits); |
||||
return rv; |
||||
} |
||||
|
||||
public int getPadBits() |
||||
{ |
||||
return padBits; |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
int end = data.length; |
||||
if (--end < 0) |
||||
{ |
||||
return 1; |
||||
} |
||||
|
||||
byte der = (byte)(data[end] & (0xFF << padBits)); |
||||
|
||||
int hc = Arrays.hashCode(data, 0, end); |
||||
hc *= 257; |
||||
hc ^= der; |
||||
return hc ^ padBits; |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof ASN1BitString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1BitString other = (ASN1BitString)o; |
||||
if (padBits != other.padBits) |
||||
{ |
||||
return false; |
||||
} |
||||
byte[] a = data, b = other.data; |
||||
int end = a.length; |
||||
if (end != b.length) |
||||
{ |
||||
return false; |
||||
} |
||||
if (--end < 0) |
||||
{ |
||||
return true; |
||||
} |
||||
for (int i = 0; i < end; ++i) |
||||
{ |
||||
if (a[i] != b[i]) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
byte derA = (byte)(a[end] & (0xFF << padBits)); |
||||
byte derB = (byte)(b[end] & (0xFF << padBits)); |
||||
|
||||
return derA == derB; |
||||
} |
||||
|
||||
static ASN1BitString 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"); |
||||
} |
||||
|
||||
if (padBits > 0 && padBits < 8) |
||||
{ |
||||
if (data[data.length - 1] != (byte)(data[data.length - 1] & (0xFF << padBits))) |
||||
{ |
||||
return new DLBitString(data, padBits); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return new DERBitString(data, padBits); |
||||
} |
||||
|
||||
public ASN1Primitive getLoadedObject() |
||||
{ |
||||
return this.toASN1Primitive(); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return new DERBitString(data, padBits); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return new DLBitString(data, padBits); |
||||
} |
||||
|
||||
abstract void encode(ASN1OutputStream out, boolean withTag) throws IOException; |
||||
} |
@ -1,169 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Public facade of ASN.1 Boolean data. |
||||
* <p> |
||||
* Use following to place a new instance of ASN.1 Boolean in your data: |
||||
* <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> |
||||
*/ |
||||
public class ASN1Boolean |
||||
extends ASN1Primitive |
||||
{ |
||||
private static final byte FALSE_VALUE = 0x00; |
||||
private static final byte TRUE_VALUE = (byte)0xFF; |
||||
|
||||
public static final ASN1Boolean FALSE = new ASN1Boolean(FALSE_VALUE); |
||||
public static final ASN1Boolean TRUE = new ASN1Boolean(TRUE_VALUE); |
||||
|
||||
private final byte value; |
||||
|
||||
/** |
||||
* 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. |
||||
* @param value true or false depending on the ASN1Boolean wanted. |
||||
* @return an ASN1Boolean instance. |
||||
*/ |
||||
public static ASN1Boolean getInstance(boolean value) |
||||
{ |
||||
return value ? TRUE : FALSE; |
||||
} |
||||
|
||||
/** |
||||
* Return an ASN1Boolean from the passed in value. |
||||
* @param value non-zero (true) or zero (false) depending on the ASN1Boolean wanted. |
||||
* @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.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
private ASN1Boolean(byte value) |
||||
{ |
||||
this.value = value; |
||||
} |
||||
|
||||
public boolean isTrue() |
||||
{ |
||||
return value != FALSE_VALUE; |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 3; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.BOOLEAN, value); |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive other) |
||||
{ |
||||
if (!(other instanceof ASN1Boolean)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1Boolean that = (ASN1Boolean)other; |
||||
|
||||
return this.isTrue() == that.isTrue(); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return isTrue() ? 1 : 0; |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return isTrue() ? TRUE : FALSE; |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return isTrue() ? "TRUE" : "FALSE"; |
||||
} |
||||
|
||||
static ASN1Boolean fromOctetString(byte[] value) |
||||
{ |
||||
if (value.length != 1) |
||||
{ |
||||
throw new IllegalArgumentException("BOOLEAN value should have 1 byte in it"); |
||||
} |
||||
|
||||
byte b = value[0]; |
||||
switch (b) |
||||
{ |
||||
case FALSE_VALUE: return FALSE; |
||||
case TRUE_VALUE: return TRUE; |
||||
default: return new ASN1Boolean(b); |
||||
} |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
/** |
||||
* Marker interface for CHOICE objects - if you implement this in a role your |
||||
* own object any attempt to tag the object implicitly will convert the tag to |
||||
* an explicit one as the encoding rules require. |
||||
* <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> |
||||
* <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 — The encoding may be primitive or constructed depending on the chosen type. |
||||
* </blockquote> |
||||
* <blockquote> |
||||
* NOTE 2 — The tag used in the identifier octets is the tag of the chosen type, |
||||
* as specified in the ASN.1 definition of the choice type. |
||||
* </blockquote> |
||||
*/ |
||||
public interface ASN1Choice |
||||
{ |
||||
// marker interface
|
||||
} |
@ -1,13 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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(); |
||||
} |
@ -1,159 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
/** |
||||
* Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs. |
||||
*/ |
||||
public class ASN1EncodableVector |
||||
{ |
||||
static final ASN1Encodable[] EMPTY_ELEMENTS = new ASN1Encodable[0]; |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private ASN1Encodable[] elements; |
||||
private int elementCount; |
||||
private boolean copyOnWrite; |
||||
|
||||
public ASN1EncodableVector() |
||||
{ |
||||
this(DEFAULT_CAPACITY); |
||||
} |
||||
|
||||
public ASN1EncodableVector(int initialCapacity) |
||||
{ |
||||
if (initialCapacity < 0) |
||||
{ |
||||
throw new IllegalArgumentException("'initialCapacity' must not be negative"); |
||||
} |
||||
|
||||
this.elements = (initialCapacity == 0) ? EMPTY_ELEMENTS : new ASN1Encodable[initialCapacity]; |
||||
this.elementCount = 0; |
||||
this.copyOnWrite = false; |
||||
} |
||||
|
||||
public void add(ASN1Encodable element) |
||||
{ |
||||
if (null == element) |
||||
{ |
||||
throw new NullPointerException("'element' cannot be null"); |
||||
} |
||||
|
||||
int capacity = elements.length; |
||||
int minCapacity = elementCount + 1; |
||||
if ((minCapacity > capacity) | copyOnWrite) |
||||
{ |
||||
reallocate(minCapacity); |
||||
} |
||||
|
||||
this.elements[elementCount] = element; |
||||
this.elementCount = minCapacity; |
||||
} |
||||
|
||||
public void addAll(ASN1EncodableVector other) |
||||
{ |
||||
if (null == other) |
||||
{ |
||||
throw new NullPointerException("'other' cannot be null"); |
||||
} |
||||
|
||||
int otherElementCount = other.size(); |
||||
if (otherElementCount < 1) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
int capacity = elements.length; |
||||
int minCapacity = elementCount + otherElementCount; |
||||
if ((minCapacity > capacity) | copyOnWrite) |
||||
{ |
||||
reallocate(minCapacity); |
||||
} |
||||
|
||||
int i = 0; |
||||
do |
||||
{ |
||||
ASN1Encodable otherElement = other.get(i); |
||||
if (null == otherElement) |
||||
{ |
||||
throw new NullPointerException("'other' elements cannot be null"); |
||||
} |
||||
|
||||
this.elements[elementCount + i] = otherElement; |
||||
} |
||||
while (++i < otherElementCount); |
||||
|
||||
this.elementCount = minCapacity; |
||||
} |
||||
|
||||
/** |
||||
* 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) |
||||
{ |
||||
if (i >= elementCount) |
||||
{ |
||||
throw new ArrayIndexOutOfBoundsException(i + " >= " + elementCount); |
||||
} |
||||
|
||||
return elements[i]; |
||||
} |
||||
|
||||
/** |
||||
* Return the size of the vector. |
||||
* |
||||
* @return the object count in the vector. |
||||
*/ |
||||
public int size() |
||||
{ |
||||
return elementCount; |
||||
} |
||||
|
||||
ASN1Encodable[] copyElements() |
||||
{ |
||||
if (0 == elementCount) |
||||
{ |
||||
return EMPTY_ELEMENTS; |
||||
} |
||||
|
||||
ASN1Encodable[] copy = new ASN1Encodable[elementCount]; |
||||
System.arraycopy(elements, 0, copy, 0, elementCount); |
||||
return copy; |
||||
} |
||||
|
||||
ASN1Encodable[] takeElements() |
||||
{ |
||||
if (0 == elementCount) |
||||
{ |
||||
return EMPTY_ELEMENTS; |
||||
} |
||||
|
||||
if (elements.length == elementCount) |
||||
{ |
||||
this.copyOnWrite = true; |
||||
return elements; |
||||
} |
||||
|
||||
ASN1Encodable[] copy = new ASN1Encodable[elementCount]; |
||||
System.arraycopy(elements, 0, copy, 0, elementCount); |
||||
return copy; |
||||
} |
||||
|
||||
private void reallocate(int minCapacity) |
||||
{ |
||||
int oldCapacity = elements.length; |
||||
int newCapacity = Math.max(oldCapacity, minCapacity + (minCapacity >> 1)); |
||||
|
||||
ASN1Encodable[] copy = new ASN1Encodable[newCapacity]; |
||||
System.arraycopy(elements, 0, copy, 0, elementCount); |
||||
|
||||
this.elements = copy; |
||||
this.copyOnWrite = false; |
||||
} |
||||
|
||||
static ASN1Encodable[] cloneElements(ASN1Encodable[] elements) |
||||
{ |
||||
return elements.length < 1 ? EMPTY_ELEMENTS : (ASN1Encodable[])elements.clone(); |
||||
} |
||||
} |
@ -1,22 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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"; |
||||
} |
@ -1,211 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.math.BigInteger; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* Class representing the ASN.1 ENUMERATED type. |
||||
*/ |
||||
public class ASN1Enumerated |
||||
extends ASN1Primitive |
||||
{ |
||||
private final byte[] bytes; |
||||
private final int start; |
||||
|
||||
/** |
||||
* 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.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Constructor from int. |
||||
* |
||||
* @param value the value of this enumerated. |
||||
*/ |
||||
public ASN1Enumerated(int value) |
||||
{ |
||||
if (value < 0) |
||||
{ |
||||
throw new IllegalArgumentException("enumerated must be non-negative"); |
||||
} |
||||
|
||||
this.bytes = BigInteger.valueOf(value).toByteArray(); |
||||
this.start = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructor from BigInteger |
||||
* |
||||
* @param value the value of this enumerated. |
||||
*/ |
||||
public ASN1Enumerated(BigInteger value) |
||||
{ |
||||
if (value.signum() < 0) |
||||
{ |
||||
throw new IllegalArgumentException("enumerated must be non-negative"); |
||||
} |
||||
|
||||
this.bytes = value.toByteArray(); |
||||
this.start = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructor from encoded BigInteger. |
||||
* |
||||
* @param bytes the value of this enumerated as an encoded BigInteger (signed). |
||||
*/ |
||||
public ASN1Enumerated(byte[] bytes) |
||||
{ |
||||
if (ASN1Integer.isMalformed(bytes)) |
||||
{ |
||||
throw new IllegalArgumentException("malformed enumerated"); |
||||
} |
||||
if (0 != (bytes[0] & 0x80)) |
||||
{ |
||||
throw new IllegalArgumentException("enumerated must be non-negative"); |
||||
} |
||||
|
||||
this.bytes = Arrays.clone(bytes); |
||||
this.start = ASN1Integer.signBytesToSkip(bytes); |
||||
} |
||||
|
||||
public BigInteger getValue() |
||||
{ |
||||
return new BigInteger(bytes); |
||||
} |
||||
|
||||
public boolean hasValue(BigInteger x) |
||||
{ |
||||
return null != x |
||||
// Fast check to avoid allocation
|
||||
&& ASN1Integer.intValue(bytes, start, ASN1Integer.SIGN_EXT_SIGNED) == x.intValue() |
||||
&& getValue().equals(x); |
||||
} |
||||
|
||||
public int intValueExact() |
||||
{ |
||||
int count = bytes.length - start; |
||||
if (count > 4) |
||||
{ |
||||
throw new ArithmeticException("ASN.1 Enumerated out of int range"); |
||||
} |
||||
|
||||
return ASN1Integer.intValue(bytes, start, ASN1Integer.SIGN_EXT_SIGNED); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, 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(enc); |
||||
} |
||||
|
||||
if (enc.length == 0) |
||||
{ |
||||
throw new IllegalArgumentException("ENUMERATED has zero length"); |
||||
} |
||||
int value = enc[0] & 0xff; |
||||
|
||||
if (value >= cache.length) |
||||
{ |
||||
return new ASN1Enumerated(enc); |
||||
} |
||||
|
||||
ASN1Enumerated possibleMatch = cache[value]; |
||||
|
||||
if (possibleMatch == null) |
||||
{ |
||||
possibleMatch = cache[value] = new ASN1Enumerated(enc); |
||||
} |
||||
|
||||
return possibleMatch; |
||||
} |
||||
} |
@ -1,44 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Exception thrown in cases of corrupted or unexpected data in a stream. |
||||
*/ |
||||
public class ASN1Exception |
||||
extends IOException |
||||
{ |
||||
private Throwable cause; |
||||
|
||||
/** |
||||
* Base constructor |
||||
* |
||||
* @param message a message concerning the exception. |
||||
*/ |
||||
ASN1Exception(String message) |
||||
{ |
||||
super(message); |
||||
} |
||||
|
||||
/** |
||||
* Constructor when this exception is due to another one. |
||||
* |
||||
* @param message a message concerning the exception. |
||||
* @param cause the exception that caused this exception to be thrown. |
||||
*/ |
||||
ASN1Exception(String message, Throwable cause) |
||||
{ |
||||
super(message); |
||||
this.cause = cause; |
||||
} |
||||
|
||||
/** |
||||
* Return the underlying cause of this exception, if any. |
||||
* |
||||
* @return the exception causing this one, null if there isn't one. |
||||
*/ |
||||
public Throwable getCause() |
||||
{ |
||||
return cause; |
||||
} |
||||
} |
@ -1,292 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Class representing the DER-type External |
||||
*/ |
||||
public abstract class ASN1External |
||||
extends ASN1Primitive |
||||
{ |
||||
protected ASN1ObjectIdentifier directReference; |
||||
protected ASN1Integer indirectReference; |
||||
protected ASN1Primitive dataValueDescriptor; |
||||
protected int encoding; |
||||
protected ASN1Primitive externalContent; |
||||
|
||||
/** |
||||
* Construct an EXTERNAL object, the input encoding vector must have exactly two elements on it. |
||||
* <p> |
||||
* Acceptable input formats are: |
||||
* <ul> |
||||
* <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li> |
||||
* <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li> |
||||
* <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li> |
||||
* </ul> |
||||
* |
||||
* @throws IllegalArgumentException if input size is wrong, or |
||||
*/ |
||||
public ASN1External(ASN1EncodableVector vector) |
||||
{ |
||||
int offset = 0; |
||||
|
||||
ASN1Primitive enc = getObjFromVector(vector, offset); |
||||
if (enc instanceof ASN1ObjectIdentifier) |
||||
{ |
||||
directReference = (ASN1ObjectIdentifier)enc; |
||||
offset++; |
||||
enc = getObjFromVector(vector, offset); |
||||
} |
||||
if (enc instanceof ASN1Integer) |
||||
{ |
||||
indirectReference = (ASN1Integer) enc; |
||||
offset++; |
||||
enc = getObjFromVector(vector, offset); |
||||
} |
||||
if (!(enc instanceof ASN1TaggedObject)) |
||||
{ |
||||
dataValueDescriptor = (ASN1Primitive) enc; |
||||
offset++; |
||||
enc = getObjFromVector(vector, offset); |
||||
} |
||||
|
||||
if (vector.size() != offset + 1) |
||||
{ |
||||
throw new IllegalArgumentException("input vector too large"); |
||||
} |
||||
|
||||
if (!(enc instanceof ASN1TaggedObject)) |
||||
{ |
||||
throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External"); |
||||
} |
||||
ASN1TaggedObject obj = (ASN1TaggedObject)enc; |
||||
setEncoding(obj.getTagNo()); |
||||
externalContent = obj.getObject(); |
||||
} |
||||
|
||||
private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index) |
||||
{ |
||||
if (v.size() <= index) |
||||
{ |
||||
throw new IllegalArgumentException("too few objects in input vector"); |
||||
} |
||||
|
||||
return v.get(index).toASN1Primitive(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of External |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param externalData The external data in its encoded form. |
||||
*/ |
||||
public ASN1External(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData) |
||||
{ |
||||
this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive()); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of External. |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param encoding The encoding to be used for the external data |
||||
* @param externalData The external data |
||||
*/ |
||||
public ASN1External(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData) |
||||
{ |
||||
setDirectReference(directReference); |
||||
setIndirectReference(indirectReference); |
||||
setDataValueDescriptor(dataValueDescriptor); |
||||
setEncoding(encoding); |
||||
setExternalContent(externalData.toASN1Primitive()); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return new DERExternal(directReference, indirectReference, dataValueDescriptor, encoding, externalContent); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return new DLExternal(directReference, indirectReference, dataValueDescriptor, encoding, externalContent); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see java.lang.Object#hashCode() |
||||
*/ |
||||
public int hashCode() |
||||
{ |
||||
int ret = 0; |
||||
if (directReference != null) |
||||
{ |
||||
ret = directReference.hashCode(); |
||||
} |
||||
if (indirectReference != null) |
||||
{ |
||||
ret ^= indirectReference.hashCode(); |
||||
} |
||||
if (dataValueDescriptor != null) |
||||
{ |
||||
ret ^= dataValueDescriptor.hashCode(); |
||||
} |
||||
ret ^= externalContent.hashCode(); |
||||
return ret; |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
return this.getEncoded().length; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#asn1Equals(com.fr.third.org.bouncycastle.asn1.ASN1Primitive) |
||||
*/ |
||||
boolean asn1Equals(ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof ASN1External)) |
||||
{ |
||||
return false; |
||||
} |
||||
if (this == o) |
||||
{ |
||||
return true; |
||||
} |
||||
ASN1External other = (ASN1External)o; |
||||
if (directReference != null) |
||||
{ |
||||
if (other.directReference == null || !other.directReference.equals(directReference)) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
if (indirectReference != null) |
||||
{ |
||||
if (other.indirectReference == null || !other.indirectReference.equals(indirectReference)) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
if (dataValueDescriptor != null) |
||||
{ |
||||
if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor)) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
return externalContent.equals(other.externalContent); |
||||
} |
||||
|
||||
/** |
||||
* Returns the data value descriptor |
||||
* @return The descriptor |
||||
*/ |
||||
public ASN1Primitive getDataValueDescriptor() |
||||
{ |
||||
return dataValueDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Returns the direct reference of the external element |
||||
* @return The reference |
||||
*/ |
||||
public ASN1ObjectIdentifier getDirectReference() |
||||
{ |
||||
return directReference; |
||||
} |
||||
|
||||
/** |
||||
* Returns the encoding of the content. Valid values are |
||||
* <ul> |
||||
* <li><code>0</code> single-ASN1-type</li> |
||||
* <li><code>1</code> OCTET STRING</li> |
||||
* <li><code>2</code> BIT STRING</li> |
||||
* </ul> |
||||
* @return The encoding |
||||
*/ |
||||
public int getEncoding() |
||||
{ |
||||
return encoding; |
||||
} |
||||
|
||||
/** |
||||
* Returns the content of this element |
||||
* @return The content |
||||
*/ |
||||
public ASN1Primitive getExternalContent() |
||||
{ |
||||
return externalContent; |
||||
} |
||||
|
||||
/** |
||||
* Returns the indirect reference of this element |
||||
* @return The reference |
||||
*/ |
||||
public ASN1Integer getIndirectReference() |
||||
{ |
||||
return indirectReference; |
||||
} |
||||
|
||||
/** |
||||
* Sets the data value descriptor |
||||
* @param dataValueDescriptor The descriptor |
||||
*/ |
||||
private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor) |
||||
{ |
||||
this.dataValueDescriptor = dataValueDescriptor; |
||||
} |
||||
|
||||
/** |
||||
* Sets the direct reference of the external element |
||||
* @param directReferemce The reference |
||||
*/ |
||||
private void setDirectReference(ASN1ObjectIdentifier directReferemce) |
||||
{ |
||||
this.directReference = directReferemce; |
||||
} |
||||
|
||||
/** |
||||
* Sets the encoding of the content. Valid values are |
||||
* <ul> |
||||
* <li><code>0</code> single-ASN1-type</li> |
||||
* <li><code>1</code> OCTET STRING</li> |
||||
* <li><code>2</code> BIT STRING</li> |
||||
* </ul> |
||||
* @param encoding The encoding |
||||
*/ |
||||
private void setEncoding(int encoding) |
||||
{ |
||||
if (encoding < 0 || encoding > 2) |
||||
{ |
||||
throw new IllegalArgumentException("invalid encoding value: " + encoding); |
||||
} |
||||
this.encoding = encoding; |
||||
} |
||||
|
||||
/** |
||||
* Sets the content of this element |
||||
* @param externalContent The content |
||||
*/ |
||||
private void setExternalContent(ASN1Primitive externalContent) |
||||
{ |
||||
this.externalContent = externalContent; |
||||
} |
||||
|
||||
/** |
||||
* Sets the indirect reference of this element |
||||
* @param indirectReference The reference |
||||
*/ |
||||
private void setIndirectReference(ASN1Integer indirectReference) |
||||
{ |
||||
this.indirectReference = indirectReference; |
||||
} |
||||
} |
@ -1,484 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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 com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.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> |
||||
* <p> |
||||
* One second resolution date+time on UTC timezone (Z) |
||||
* with 4 digit year (valid from 0001 to 9999). |
||||
* </p><p> |
||||
* Timestamp format is: yyyymmddHHMMSS'Z' |
||||
* </p><p> |
||||
* <h2>X.690</h2> |
||||
* This is what is called "restricted string", |
||||
* and it uses ASCII characters to encode digits and supplemental data. |
||||
* |
||||
* <h3>11: Restrictions on BER employed by both CER and DER</h3> |
||||
* <h4>11.7 GeneralizedTime </h4> |
||||
* <p> |
||||
* <b>11.7.1</b> The encoding shall terminate with a "Z", |
||||
* as described in the ITU-T Rec. X.680 | ISO/IEC 8824-1 clause on |
||||
* GeneralizedTime. |
||||
* </p><p> |
||||
* <b>11.7.2</b> The seconds element shall always be present. |
||||
* </p> |
||||
* <p> |
||||
* <b>11.7.3</b> The fractional-seconds elements, if present, |
||||
* shall omit all trailing zeros; if the elements correspond to 0, |
||||
* they shall be wholly omitted, and the decimal point element also |
||||
* shall be omitted. |
||||
*/ |
||||
public class ASN1GeneralizedTime |
||||
extends ASN1Primitive |
||||
{ |
||||
protected 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.getInstance(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'", DateUtil.EN_Locale); |
||||
|
||||
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) |
||||
{ |
||||
if (bytes.length < 4) |
||||
{ |
||||
throw new IllegalArgumentException("GeneralizedTime string too short"); |
||||
} |
||||
this.time = bytes; |
||||
|
||||
if (!(isDigit(0) && isDigit(1) && isDigit(2) && isDigit(3))) |
||||
{ |
||||
throw new IllegalArgumentException("illegal characters in GeneralizedTime string"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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. |
||||
* @return a String representation of the time. |
||||
*/ |
||||
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() - 6; |
||||
char sign = stime.charAt(signPos); |
||||
if ((sign == '-' || sign == '+') && stime.indexOf("GMT") == signPos - 3) |
||||
{ |
||||
// already a GMT string!
|
||||
return stime; |
||||
} |
||||
|
||||
signPos = stime.length() - 5; |
||||
sign = stime.charAt(signPos); |
||||
if (sign == '-' || sign == '+') |
||||
{ |
||||
return stime.substring(0, signPos) |
||||
+ "GMT" |
||||
+ stime.substring(signPos, signPos + 3) |
||||
+ ":" |
||||
+ stime.substring(signPos + 3); |
||||
} |
||||
|
||||
signPos = stime.length() - 3; |
||||
sign = stime.charAt(signPos); |
||||
if (sign == '-' || sign == '+') |
||||
{ |
||||
return stime.substring(0, signPos) |
||||
+ "GMT" |
||||
+ stime.substring(signPos) |
||||
+ ":00"; |
||||
} |
||||
} |
||||
return stime + calculateGMTOffset(stime); |
||||
} |
||||
|
||||
private String calculateGMTOffset(String stime) |
||||
{ |
||||
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()) |
||||
{ |
||||
if (hasFractionalSeconds()) |
||||
{ |
||||
stime = pruneFractionalSeconds(stime); |
||||
} |
||||
SimpleDateFormat dateF = calculateGMTDateFormat(); |
||||
if (timeZone.inDaylightTime( |
||||
dateF.parse(stime + "GMT" + sign + convert(hours) + ":" + convert(minutes)))) |
||||
{ |
||||
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 SimpleDateFormat calculateGMTDateFormat() |
||||
{ |
||||
SimpleDateFormat dateF; |
||||
|
||||
if (hasFractionalSeconds()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz"); |
||||
} |
||||
else if (hasSeconds()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); |
||||
} |
||||
else if (hasMinutes()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmz"); |
||||
} |
||||
else |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHz"); |
||||
} |
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, "Z")); |
||||
return dateF; |
||||
} |
||||
|
||||
private String pruneFractionalSeconds(String origTime) |
||||
{ |
||||
// java misinterprets extra digits as being milliseconds...
|
||||
String frac = origTime.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); |
||||
origTime = origTime.substring(0, 14) + frac; |
||||
} |
||||
else if (index - 1 == 1) |
||||
{ |
||||
frac = frac.substring(0, index) + "00" + frac.substring(index); |
||||
origTime = origTime.substring(0, 14) + frac; |
||||
} |
||||
else if (index - 1 == 2) |
||||
{ |
||||
frac = frac.substring(0, index) + "0" + frac.substring(index); |
||||
origTime = origTime.substring(0, 14) + frac; |
||||
} |
||||
|
||||
return origTime; |
||||
} |
||||
|
||||
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 if (hasSeconds()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'"); |
||||
} |
||||
else if (hasMinutes()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmm'Z'"); |
||||
} |
||||
else |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHH'Z'"); |
||||
} |
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, "Z")); |
||||
} |
||||
else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0) |
||||
{ |
||||
d = this.getTime(); |
||||
dateF = calculateGMTDateFormat(); |
||||
} |
||||
else |
||||
{ |
||||
if (hasFractionalSeconds()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); |
||||
} |
||||
else if (hasSeconds()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmmss"); |
||||
} |
||||
else if (hasMinutes()) |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHHmm"); |
||||
} |
||||
else |
||||
{ |
||||
dateF = new SimpleDateFormat("yyyyMMddHH"); |
||||
} |
||||
|
||||
dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID())); |
||||
} |
||||
|
||||
if (hasFractionalSeconds()) |
||||
{ |
||||
d = pruneFractionalSeconds(d); |
||||
} |
||||
|
||||
return DateUtil.epochAdjust(dateF.parse(d)); |
||||
} |
||||
|
||||
protected boolean hasFractionalSeconds() |
||||
{ |
||||
for (int i = 0; i != time.length; i++) |
||||
{ |
||||
if (time[i] == '.') |
||||
{ |
||||
if (i == 14) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
protected boolean hasSeconds() |
||||
{ |
||||
return isDigit(12) && isDigit(13); |
||||
} |
||||
|
||||
protected boolean hasMinutes() |
||||
{ |
||||
return isDigit(10) && isDigit(11); |
||||
} |
||||
|
||||
private boolean isDigit(int pos) |
||||
{ |
||||
return time.length > pos && time[pos] >= '0' && time[pos] <= '9'; |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
int length = time.length; |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.GENERALIZED_TIME, time); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return new DERGeneralizedTime(time); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return new DERGeneralizedTime(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); |
||||
} |
||||
} |
@ -1,30 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Basic class for streaming generators. |
||||
*/ |
||||
public abstract class ASN1Generator |
||||
{ |
||||
// TODO This is problematic if we want an isolating buffer for all ASN.1 writes
|
||||
protected OutputStream _out; |
||||
|
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @param out |
||||
* the end output stream that object encodings are written to. |
||||
*/ |
||||
public ASN1Generator(OutputStream out) |
||||
{ |
||||
_out = out; |
||||
} |
||||
|
||||
/** |
||||
* Return the actual stream object encodings are written to. |
||||
* |
||||
* @return the stream that is directly encoded to. |
||||
*/ |
||||
public abstract OutputStream getRawOutputStream(); |
||||
} |
@ -1,506 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.EOFException; |
||||
import java.io.FilterInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.io.Streams; |
||||
|
||||
/** |
||||
* A general purpose ASN.1 decoder - note: this class differs from the |
||||
* others in that it returns null after it has read the last object in |
||||
* the stream. If an ASN.1 NULL is encountered a DER/BER Null object is |
||||
* returned. |
||||
*/ |
||||
public class ASN1InputStream |
||||
extends FilterInputStream |
||||
implements 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, false); |
||||
} |
||||
|
||||
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, limit); |
||||
|
||||
if ((tag & APPLICATION) != 0) |
||||
{ |
||||
return new DLApplicationSpecific(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 = readVector(defIn); |
||||
ASN1OctetString[] strings = new ASN1OctetString[v.size()]; |
||||
|
||||
for (int i = 0; i != strings.length; i++) |
||||
{ |
||||
ASN1Encodable asn1Obj = v.get(i); |
||||
if (asn1Obj instanceof ASN1OctetString) |
||||
{ |
||||
strings[i] = (ASN1OctetString)asn1Obj; |
||||
} |
||||
else |
||||
{ |
||||
throw new ASN1Exception("unknown object encountered in constructed OCTET STRING: " + asn1Obj.getClass()); |
||||
} |
||||
} |
||||
|
||||
return new BEROctetString(strings); |
||||
case SEQUENCE: |
||||
if (lazyEvaluate) |
||||
{ |
||||
return new LazyEncodedSequence(defIn.toByteArray()); |
||||
} |
||||
else |
||||
{ |
||||
return DLFactory.createSequence(readVector(defIn)); |
||||
} |
||||
case SET: |
||||
return DLFactory.createSet(readVector(defIn)); |
||||
case EXTERNAL: |
||||
return new DLExternal(readVector(defIn)); |
||||
default: |
||||
throw new IOException("unknown tag " + tagNo + " encountered"); |
||||
} |
||||
} |
||||
|
||||
return createPrimitiveDERObject(tagNo, defIn, tmpBuffers); |
||||
} |
||||
|
||||
ASN1EncodableVector readVector(DefiniteLengthInputStream dIn) throws IOException |
||||
{ |
||||
if (dIn.getRemaining() < 1) |
||||
{ |
||||
return new ASN1EncodableVector(0); |
||||
} |
||||
|
||||
ASN1InputStream subStream = new ASN1InputStream(dIn); |
||||
ASN1EncodableVector v = new ASN1EncodableVector(); |
||||
ASN1Primitive p; |
||||
while ((p = subStream.readObject()) != null) |
||||
{ |
||||
v.add(p); |
||||
} |
||||
return v; |
||||
} |
||||
|
||||
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, boolean isParsing) |
||||
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 && !isParsing) // after all we must have read at least 1 byte
|
||||
{ |
||||
throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit); |
||||
} |
||||
} |
||||
|
||||
return length; |
||||
} |
||||
|
||||
private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers) |
||||
throws IOException |
||||
{ |
||||
int len = defIn.getRemaining(); |
||||
if (len >= tmpBuffers.length) |
||||
{ |
||||
return defIn.toByteArray(); |
||||
} |
||||
|
||||
byte[] buf = tmpBuffers[len]; |
||||
if (buf == null) |
||||
{ |
||||
buf = tmpBuffers[len] = new byte[len]; |
||||
} |
||||
|
||||
defIn.readAllIntoByteArray(buf); |
||||
|
||||
return buf; |
||||
} |
||||
|
||||
private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn) |
||||
throws IOException |
||||
{ |
||||
int remainingBytes = defIn.getRemaining(); |
||||
if (0 != (remainingBytes & 1)) |
||||
{ |
||||
throw new IOException("malformed BMPString encoding encountered"); |
||||
} |
||||
|
||||
char[] string = new char[remainingBytes / 2]; |
||||
int stringPos = 0; |
||||
|
||||
byte[] buf = new byte[8]; |
||||
while (remainingBytes >= 8) |
||||
{ |
||||
if (Streams.readFully(defIn, buf, 0, 8) != 8) |
||||
{ |
||||
throw new EOFException("EOF encountered in middle of BMPString"); |
||||
} |
||||
|
||||
string[stringPos ] = (char)((buf[0] << 8) | (buf[1] & 0xFF)); |
||||
string[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF)); |
||||
string[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF)); |
||||
string[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF)); |
||||
stringPos += 4; |
||||
remainingBytes -= 8; |
||||
} |
||||
if (remainingBytes > 0) |
||||
{ |
||||
if (Streams.readFully(defIn, buf, 0, remainingBytes) != remainingBytes) |
||||
{ |
||||
throw new EOFException("EOF encountered in middle of BMPString"); |
||||
} |
||||
|
||||
int bufPos = 0; |
||||
do |
||||
{ |
||||
int b1 = buf[bufPos++] << 8; |
||||
int b2 = buf[bufPos++] & 0xFF; |
||||
string[stringPos++] = (char)(b1 | b2); |
||||
} |
||||
while (bufPos < remainingBytes); |
||||
} |
||||
|
||||
if (0 != defIn.getRemaining() || string.length != stringPos) |
||||
{ |
||||
throw new IllegalStateException(); |
||||
} |
||||
|
||||
return string; |
||||
} |
||||
|
||||
static ASN1Primitive createPrimitiveDERObject( |
||||
int tagNo, |
||||
DefiniteLengthInputStream defIn, |
||||
byte[][] tmpBuffers) |
||||
throws IOException |
||||
{ |
||||
switch (tagNo) |
||||
{ |
||||
case BIT_STRING: |
||||
return ASN1BitString.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()); |
||||
case GRAPHIC_STRING: |
||||
return new DERGraphicString(defIn.toByteArray()); |
||||
case VIDEOTEX_STRING: |
||||
return new DERVideotexString(defIn.toByteArray()); |
||||
default: |
||||
throw new IOException("unknown tag " + tagNo + " encountered"); |
||||
} |
||||
} |
||||
} |
@ -1,288 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.math.BigInteger; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Properties; |
||||
|
||||
/** |
||||
* Class representing the ASN.1 INTEGER type. |
||||
*/ |
||||
public class ASN1Integer |
||||
extends ASN1Primitive |
||||
{ |
||||
static final int SIGN_EXT_SIGNED = 0xFFFFFFFF; |
||||
static final int SIGN_EXT_UNSIGNED = 0xFF; |
||||
|
||||
private final byte[] bytes; |
||||
private final int start; |
||||
|
||||
/** |
||||
* Return an integer from the passed in object. |
||||
* |
||||
* @param obj an ASN1Integer or an object that can be converted into one. |
||||
* @return an ASN1Integer instance. |
||||
* @throws IllegalArgumentException if the object cannot be converted. |
||||
*/ |
||||
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. |
||||
* @return an ASN1Integer instance. |
||||
* @throws IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
*/ |
||||
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(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Construct an INTEGER from the passed in long value. |
||||
* |
||||
* @param value the long representing the value desired. |
||||
*/ |
||||
public ASN1Integer(long value) |
||||
{ |
||||
this.bytes = BigInteger.valueOf(value).toByteArray(); |
||||
this.start = 0; |
||||
} |
||||
|
||||
/** |
||||
* Construct an INTEGER from the passed in BigInteger value. |
||||
* |
||||
* @param value the BigInteger representing the value desired. |
||||
*/ |
||||
public ASN1Integer(BigInteger value) |
||||
{ |
||||
this.bytes = value.toByteArray(); |
||||
this.start = 0; |
||||
} |
||||
|
||||
/** |
||||
* Construct an INTEGER from the passed in byte array. |
||||
* |
||||
* <p> |
||||
* <b>NB: Strict Validation applied by default.</b> |
||||
* </p> |
||||
* <p> |
||||
* It has turned out that there are still a few applications that struggle with |
||||
* the ASN.1 BER encoding rules for an INTEGER as described in: |
||||
* |
||||
* https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
|
||||
* Section 8.3.2. |
||||
* </p> |
||||
* <p> |
||||
* Users can set the 'com.fr.third.org.bouncycastle.asn1.allow_unsafe_integer' to 'true' |
||||
* and a looser validation will be applied. Users must recognise that this is |
||||
* not ideal and may pave the way for an exploit based around a faulty encoding |
||||
* in the future. |
||||
* </p> |
||||
* |
||||
* @param bytes the byte array representing a 2's complement encoding of a BigInteger. |
||||
*/ |
||||
public ASN1Integer(byte[] bytes) |
||||
{ |
||||
this(bytes, true); |
||||
} |
||||
|
||||
ASN1Integer(byte[] bytes, boolean clone) |
||||
{ |
||||
if (isMalformed(bytes)) |
||||
{ |
||||
throw new IllegalArgumentException("malformed integer"); |
||||
} |
||||
|
||||
this.bytes = clone ? Arrays.clone(bytes) : bytes; |
||||
this.start = signBytesToSkip(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); |
||||
} |
||||
|
||||
public BigInteger getValue() |
||||
{ |
||||
return new BigInteger(bytes); |
||||
} |
||||
|
||||
public boolean hasValue(BigInteger x) |
||||
{ |
||||
return null != x |
||||
// Fast check to avoid allocation
|
||||
&& intValue(bytes, start, SIGN_EXT_SIGNED) == x.intValue() |
||||
&& getValue().equals(x); |
||||
} |
||||
|
||||
public int intPositiveValueExact() |
||||
{ |
||||
int count = bytes.length - start; |
||||
if (count > 4 || (count == 4 && 0 != (bytes[start] & 0x80))) |
||||
{ |
||||
throw new ArithmeticException("ASN.1 Integer out of positive int range"); |
||||
} |
||||
|
||||
return intValue(bytes, start, SIGN_EXT_UNSIGNED); |
||||
} |
||||
|
||||
public int intValueExact() |
||||
{ |
||||
int count = bytes.length - start; |
||||
if (count > 4) |
||||
{ |
||||
throw new ArithmeticException("ASN.1 Integer out of int range"); |
||||
} |
||||
|
||||
return intValue(bytes, start, SIGN_EXT_SIGNED); |
||||
} |
||||
|
||||
public long longValueExact() |
||||
{ |
||||
int count = bytes.length - start; |
||||
if (count > 8) |
||||
{ |
||||
throw new ArithmeticException("ASN.1 Integer out of long range"); |
||||
} |
||||
|
||||
return longValue(bytes, start, SIGN_EXT_SIGNED); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.INTEGER, bytes); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(bytes); |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof ASN1Integer)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1Integer other = (ASN1Integer)o; |
||||
|
||||
return Arrays.areEqual(this.bytes, other.bytes); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getValue().toString(); |
||||
} |
||||
|
||||
static int intValue(byte[] bytes, int start, int signExt) |
||||
{ |
||||
int length = bytes.length; |
||||
int pos = Math.max(start, length - 4); |
||||
|
||||
int val = bytes[pos] & signExt; |
||||
while (++pos < length) |
||||
{ |
||||
val = (val << 8) | (bytes[pos] & SIGN_EXT_UNSIGNED); |
||||
} |
||||
return val; |
||||
} |
||||
|
||||
static long longValue(byte[] bytes, int start, int signExt) |
||||
{ |
||||
int length = bytes.length; |
||||
int pos = Math.max(start, length - 8); |
||||
|
||||
long val = bytes[pos] & signExt; |
||||
while (++pos < length) |
||||
{ |
||||
val = (val << 8) | (bytes[pos] & SIGN_EXT_UNSIGNED); |
||||
} |
||||
return val; |
||||
} |
||||
|
||||
/** |
||||
* Apply the correct validation for an INTEGER primitive following the BER rules. |
||||
* |
||||
* @param bytes The raw encoding of the integer. |
||||
* @return true if the (in)put fails this validation. |
||||
*/ |
||||
static boolean isMalformed(byte[] bytes) |
||||
{ |
||||
switch (bytes.length) |
||||
{ |
||||
case 0: |
||||
return true; |
||||
case 1: |
||||
return false; |
||||
default: |
||||
return bytes[0] == (bytes[1] >> 7) |
||||
// Apply loose validation, see note in public constructor ASN1Integer(byte[])
|
||||
&& !Properties.isOverrideSet("com.fr.third.org.bouncycastle.asn1.allow_unsafe_integer"); |
||||
} |
||||
} |
||||
|
||||
static int signBytesToSkip(byte[] bytes) |
||||
{ |
||||
int pos = 0, last = bytes.length - 1; |
||||
while (pos < last |
||||
&& bytes[pos] == (bytes[pos + 1] >> 7)) |
||||
{ |
||||
++pos; |
||||
} |
||||
return pos; |
||||
} |
||||
} |
@ -1,82 +0,0 @@
|
||||
/***************************************************************/ |
||||
/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/ |
||||
/***************************************************************/ |
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A NULL object - use DERNull.INSTANCE for populating structures. |
||||
*/ |
||||
public abstract class ASN1Null |
||||
extends ASN1Primitive |
||||
{ |
||||
ASN1Null() |
||||
{ |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Return an instance of ASN.1 NULL from the passed in object. |
||||
* <p> |
||||
* Accepted inputs: |
||||
* <ul> |
||||
* <li> null → 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, boolean withTag) throws IOException; |
||||
|
||||
public String toString() |
||||
{ |
||||
return "NULL"; |
||||
} |
||||
} |
@ -1,92 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Encodable; |
||||
|
||||
/** |
||||
* Base class for defining an ASN.1 object. |
||||
*/ |
||||
public abstract class ASN1Object |
||||
implements ASN1Encodable, Encodable |
||||
{ |
||||
public void encodeTo(OutputStream output) throws IOException |
||||
{ |
||||
ASN1OutputStream.create(output).writeObject(this); |
||||
} |
||||
|
||||
public void encodeTo(OutputStream output, String encoding) throws IOException |
||||
{ |
||||
ASN1OutputStream.create(output, encoding).writeObject(this); |
||||
} |
||||
|
||||
/** |
||||
* 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(); |
||||
encodeTo(bOut); |
||||
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 |
||||
{ |
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
||||
encodeTo(bOut, encoding); |
||||
return bOut.toByteArray(); |
||||
} |
||||
|
||||
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()); |
||||
} |
||||
|
||||
/** |
||||
* 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(); |
||||
} |
@ -1,481 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.math.BigInteger; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ConcurrentMap; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* Class representing the ASN.1 OBJECT IDENTIFIER type. |
||||
*/ |
||||
public class ASN1ObjectIdentifier |
||||
extends ASN1Primitive |
||||
{ |
||||
private final 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. |
||||
* @return an ASN1ObjectIdentifier instance, or null. |
||||
* @throws IllegalArgumentException if the object cannot be converted. |
||||
*/ |
||||
public static ASN1ObjectIdentifier getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof ASN1ObjectIdentifier) |
||||
{ |
||||
return (ASN1ObjectIdentifier)obj; |
||||
} |
||||
|
||||
if (obj instanceof ASN1Encodable) |
||||
{ |
||||
ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive(); |
||||
|
||||
if (primitive instanceof ASN1ObjectIdentifier) |
||||
{ |
||||
return (ASN1ObjectIdentifier)primitive; |
||||
} |
||||
} |
||||
|
||||
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. |
||||
* @return an ASN1ObjectIdentifier instance, or null. |
||||
* @throws IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
*/ |
||||
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(o).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 NullPointerException("'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)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private 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, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.OBJECT_IDENTIFIER, getBody()); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return identifier.hashCode(); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (o == this) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
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) |
||||
{ |
||||
int digitCount = 0; |
||||
|
||||
int pos = branchID.length(); |
||||
while (--pos >= start) |
||||
{ |
||||
char ch = branchID.charAt(pos); |
||||
|
||||
if (ch == '.') |
||||
{ |
||||
if (0 == digitCount |
||||
|| (digitCount > 1 && branchID.charAt(pos + 1) == '0')) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
digitCount = 0; |
||||
} |
||||
else if ('0' <= ch && ch <= '9') |
||||
{ |
||||
++digitCount; |
||||
} |
||||
else |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
if (0 == digitCount |
||||
|| (digitCount > 1 && branchID.charAt(pos + 1) == '0')) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
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); |
||||
} |
||||
|
||||
/** |
||||
* Intern will return a reference to a pooled version of this object, unless it |
||||
* is not present in which case intern will add it. |
||||
* <p> |
||||
* The pool is also used by the ASN.1 parsers to limit the number of duplicated OID |
||||
* objects in circulation. |
||||
* </p> |
||||
* |
||||
* @return a reference to the identifier in the pool. |
||||
*/ |
||||
public ASN1ObjectIdentifier intern() |
||||
{ |
||||
final OidHandle hdl = new OidHandle(getBody()); |
||||
ASN1ObjectIdentifier oid = pool.get(hdl); |
||||
if (oid == null) |
||||
{ |
||||
oid = pool.putIfAbsent(hdl, this); |
||||
if (oid == null) |
||||
{ |
||||
oid = this; |
||||
} |
||||
} |
||||
return oid; |
||||
} |
||||
|
||||
private static final ConcurrentMap<OidHandle, ASN1ObjectIdentifier> pool = new ConcurrentHashMap<OidHandle, ASN1ObjectIdentifier>(); |
||||
|
||||
private static class OidHandle |
||||
{ |
||||
private final int key; |
||||
private final byte[] enc; |
||||
|
||||
OidHandle(byte[] enc) |
||||
{ |
||||
this.key = Arrays.hashCode(enc); |
||||
this.enc = enc; |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return key; |
||||
} |
||||
|
||||
public boolean equals(Object o) |
||||
{ |
||||
if (o instanceof OidHandle) |
||||
{ |
||||
return Arrays.areEqual(enc, ((OidHandle)o).enc); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
|
||||
static ASN1ObjectIdentifier fromOctetString(byte[] enc) |
||||
{ |
||||
final OidHandle hdl = new OidHandle(enc); |
||||
ASN1ObjectIdentifier oid = pool.get(hdl); |
||||
if (oid == null) |
||||
{ |
||||
return new ASN1ObjectIdentifier(enc); |
||||
} |
||||
return oid; |
||||
} |
||||
} |
@ -1,301 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
import com.fr.third.org.bouncycastle.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> |
||||
* <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 — 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. |
||||
* </p> |
||||
* <blockquote> |
||||
* NOTE — Each such encoding includes identifier, length, and contents octets, |
||||
* and may include end-of-contents octets if it is constructed. |
||||
* </blockquote> |
||||
* <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.</p> |
||||
* <blockquote> |
||||
* NOTE — A segment may be of size zero, i.e. contain no octets. |
||||
* </blockquote> |
||||
* <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. |
||||
* </p> |
||||
* <blockquote> |
||||
* NOTE 1 — As a consequence of this recursion, |
||||
* each encoding in the contents octets may itself |
||||
* be primitive or constructed. |
||||
* However, such encodings will usually be primitive. |
||||
* </blockquote> |
||||
* <blockquote> |
||||
* NOTE 2 — In particular, the tags in the contents octets are always universal class, number 4. |
||||
* </blockquote> |
||||
* <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><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.) |
||||
*/ |
||||
public abstract class ASN1OctetString |
||||
extends ASN1Primitive |
||||
implements ASN1OctetStringParser |
||||
{ |
||||
byte[] string; |
||||
|
||||
/** |
||||
* return an Octet String from a tagged object. |
||||
* |
||||
* @param taggedObject 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 taggedObject, |
||||
boolean explicit) |
||||
{ |
||||
if (explicit) |
||||
{ |
||||
if (!taggedObject.isExplicit()) |
||||
{ |
||||
throw new IllegalArgumentException("object implicit - explicit expected."); |
||||
} |
||||
|
||||
return getInstance(taggedObject.getObject()); |
||||
} |
||||
|
||||
ASN1Primitive o = taggedObject.getObject(); |
||||
|
||||
/* |
||||
* constructed object which appears to be explicitly tagged and it's really implicit means |
||||
* we have to add the surrounding octet string. |
||||
*/ |
||||
if (taggedObject.isExplicit()) |
||||
{ |
||||
ASN1OctetString singleSegment = getInstance(o); |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return new BEROctetString(new ASN1OctetString[]{ singleSegment }); |
||||
} |
||||
|
||||
// TODO Should really be similar to the BERTaggedObject case above:
|
||||
// return new DLOctetString(new ASN1OctetString[]{ singleSegment });
|
||||
return (ASN1OctetString)new BEROctetString(new ASN1OctetString[]{ singleSegment }).toDLObject(); |
||||
} |
||||
|
||||
if (o instanceof ASN1OctetString) |
||||
{ |
||||
ASN1OctetString s = (ASN1OctetString)o; |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return s; |
||||
} |
||||
|
||||
return (ASN1OctetString)s.toDLObject(); |
||||
} |
||||
|
||||
/* |
||||
* in this case the parser returns a sequence, convert it into an octet string. |
||||
*/ |
||||
if (o instanceof ASN1Sequence) |
||||
{ |
||||
ASN1Sequence s = (ASN1Sequence)o; |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return BEROctetString.fromSequence(s); |
||||
} |
||||
|
||||
// TODO Should really be similar to the BERTaggedObject case above:
|
||||
// return DLOctetString.fromSequence(s);
|
||||
return (ASN1OctetString)BEROctetString.fromSequence(s).toDLObject(); |
||||
} |
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + taggedObject.getClass().getName()); |
||||
} |
||||
|
||||
/** |
||||
* 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 getInstance(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()); |
||||
} |
||||
|
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @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, boolean withTag) throws IOException; |
||||
|
||||
public String toString() |
||||
{ |
||||
return "#" + Strings.fromByteArray(Hex.encode(string)); |
||||
} |
||||
} |
@ -1,17 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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(); |
||||
} |
@ -1,321 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.util.Enumeration; |
||||
|
||||
/** |
||||
* Stream that produces output based on the default encoding for the passed in objects. |
||||
*/ |
||||
public class ASN1OutputStream |
||||
{ |
||||
public static ASN1OutputStream create(OutputStream out) |
||||
{ |
||||
return new ASN1OutputStream(out); |
||||
} |
||||
|
||||
public static ASN1OutputStream create(OutputStream out, String encoding) |
||||
{ |
||||
if (encoding.equals(ASN1Encoding.DER)) |
||||
{ |
||||
return new DEROutputStream(out); |
||||
} |
||||
else if (encoding.equals(ASN1Encoding.DL)) |
||||
{ |
||||
return new DLOutputStream(out); |
||||
} |
||||
else |
||||
{ |
||||
return new ASN1OutputStream(out); |
||||
} |
||||
} |
||||
|
||||
private OutputStream os; |
||||
|
||||
/** |
||||
* @deprecated Use {@link ASN1OutputStream#create(OutputStream)} instead. |
||||
*/ |
||||
public ASN1OutputStream(OutputStream os) |
||||
{ |
||||
this.os = os; |
||||
} |
||||
|
||||
final 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); |
||||
} |
||||
} |
||||
|
||||
final void write(int b) |
||||
throws IOException |
||||
{ |
||||
os.write(b); |
||||
} |
||||
|
||||
final void write(byte[] bytes, int off, int len) |
||||
throws IOException |
||||
{ |
||||
os.write(bytes, off, len); |
||||
} |
||||
|
||||
final void writeElements(ASN1Encodable[] elements) |
||||
throws IOException |
||||
{ |
||||
int count = elements.length; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive primitive = elements[i].toASN1Primitive(); |
||||
|
||||
writePrimitive(primitive, true); |
||||
} |
||||
} |
||||
|
||||
final void writeElements(Enumeration elements) |
||||
throws IOException |
||||
{ |
||||
while (elements.hasMoreElements()) |
||||
{ |
||||
ASN1Primitive primitive = ((ASN1Encodable)elements.nextElement()).toASN1Primitive(); |
||||
|
||||
writePrimitive(primitive, true); |
||||
} |
||||
} |
||||
|
||||
final void writeEncoded( |
||||
boolean withTag, |
||||
int tag, |
||||
byte contents) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
writeLength(1); |
||||
write(contents); |
||||
} |
||||
|
||||
final void writeEncoded( |
||||
boolean withTag, |
||||
int tag, |
||||
byte[] contents) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
writeLength(contents.length); |
||||
write(contents, 0, contents.length); |
||||
} |
||||
|
||||
final void writeEncoded( |
||||
boolean withTag, |
||||
int tag, |
||||
byte[] contents, |
||||
int contentsOff, |
||||
int contentsLen) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
writeLength(contentsLen); |
||||
write(contents, contentsOff, contentsLen); |
||||
} |
||||
|
||||
final void writeEncoded( |
||||
boolean withTag, |
||||
int tag, |
||||
byte headByte, |
||||
byte[] tailBytes) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
writeLength(1 + tailBytes.length); |
||||
write(headByte); |
||||
write(tailBytes, 0, tailBytes.length); |
||||
} |
||||
|
||||
final void writeEncoded( |
||||
boolean withTag, |
||||
int tag, |
||||
byte headByte, |
||||
byte[] body, |
||||
int bodyOff, |
||||
int bodyLen, |
||||
byte tailByte) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
writeLength(2 + bodyLen); |
||||
write(headByte); |
||||
write(body, bodyOff, bodyLen); |
||||
write(tailByte); |
||||
} |
||||
|
||||
final void writeEncoded(boolean withTag, int flags, int tagNo, byte[] contents) |
||||
throws IOException |
||||
{ |
||||
writeTag(withTag, flags, tagNo); |
||||
writeLength(contents.length); |
||||
write(contents, 0, contents.length); |
||||
} |
||||
|
||||
final void writeEncodedIndef(boolean withTag, int flags, int tagNo, byte[] contents) |
||||
throws IOException |
||||
{ |
||||
writeTag(withTag, flags, tagNo); |
||||
write(0x80); |
||||
write(contents, 0, contents.length); |
||||
write(0x00); |
||||
write(0x00); |
||||
} |
||||
|
||||
final void writeEncodedIndef(boolean withTag, int tag, ASN1Encodable[] elements) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
write(0x80); |
||||
writeElements(elements); |
||||
write(0x00); |
||||
write(0x00); |
||||
} |
||||
|
||||
final void writeEncodedIndef(boolean withTag, int tag, Enumeration elements) |
||||
throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
write(tag); |
||||
} |
||||
write(0x80); |
||||
writeElements(elements); |
||||
write(0x00); |
||||
write(0x00); |
||||
} |
||||
|
||||
final void writeTag(boolean withTag, int flags, int tagNo) |
||||
throws IOException |
||||
{ |
||||
if (!withTag) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void writeObject(ASN1Encodable obj) throws IOException |
||||
{ |
||||
if (null == obj) |
||||
{ |
||||
throw new IOException("null object detected"); |
||||
} |
||||
|
||||
writePrimitive(obj.toASN1Primitive(), true); |
||||
flushInternal(); |
||||
} |
||||
|
||||
public void writeObject(ASN1Primitive primitive) throws IOException |
||||
{ |
||||
if (null == primitive) |
||||
{ |
||||
throw new IOException("null object detected"); |
||||
} |
||||
|
||||
writePrimitive(primitive, true); |
||||
flushInternal(); |
||||
} |
||||
|
||||
void writePrimitive(ASN1Primitive primitive, boolean withTag) throws IOException |
||||
{ |
||||
primitive.encode(this, withTag); |
||||
} |
||||
|
||||
public void close() |
||||
throws IOException |
||||
{ |
||||
os.close(); |
||||
} |
||||
|
||||
public void flush() |
||||
throws IOException |
||||
{ |
||||
os.flush(); |
||||
} |
||||
|
||||
void flushInternal() |
||||
throws IOException |
||||
{ |
||||
// Placeholder to support future internal buffering
|
||||
} |
||||
|
||||
DEROutputStream getDERSubStream() |
||||
{ |
||||
return new DEROutputStream(os); |
||||
} |
||||
|
||||
ASN1OutputStream getDLSubStream() |
||||
{ |
||||
return new DLOutputStream(os); |
||||
} |
||||
} |
@ -1,42 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
/** |
||||
* Exception thrown when correctly encoded, but unexpected data is found in a stream while building an object. |
||||
*/ |
||||
public class ASN1ParsingException |
||||
extends IllegalStateException |
||||
{ |
||||
private Throwable cause; |
||||
|
||||
/** |
||||
* Base constructor |
||||
* |
||||
* @param message a message concerning the exception. |
||||
*/ |
||||
public ASN1ParsingException(String message) |
||||
{ |
||||
super(message); |
||||
} |
||||
|
||||
/** |
||||
* Constructor when this exception is due to another one. |
||||
* |
||||
* @param message a message concerning the exception. |
||||
* @param cause the exception that caused this exception to be thrown. |
||||
*/ |
||||
public ASN1ParsingException(String message, Throwable cause) |
||||
{ |
||||
super(message); |
||||
this.cause = cause; |
||||
} |
||||
|
||||
/** |
||||
* Return the underlying cause of this exception, if any. |
||||
* |
||||
* @return the exception causing this one, null if there isn't one. |
||||
*/ |
||||
public Throwable getCause() |
||||
{ |
||||
return cause; |
||||
} |
||||
} |
@ -1,121 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Base class for ASN.1 primitive objects. These are the actual objects used to generate byte encodings. |
||||
*/ |
||||
public abstract class ASN1Primitive |
||||
extends ASN1Object |
||||
{ |
||||
ASN1Primitive() |
||||
{ |
||||
} |
||||
|
||||
public void encodeTo(OutputStream output) throws IOException |
||||
{ |
||||
ASN1OutputStream.create(output).writeObject(this); |
||||
} |
||||
|
||||
public void encodeTo(OutputStream output, String encoding) throws IOException |
||||
{ |
||||
ASN1OutputStream.create(output, encoding).writeObject(this); |
||||
} |
||||
|
||||
/** |
||||
* 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, or parsing the stream did not exhaust the available data. |
||||
*/ |
||||
public static ASN1Primitive fromByteArray(byte[] data) |
||||
throws IOException |
||||
{ |
||||
ASN1InputStream aIn = new ASN1InputStream(data); |
||||
|
||||
try |
||||
{ |
||||
ASN1Primitive o = aIn.readObject(); |
||||
|
||||
if (aIn.available() != 0) |
||||
{ |
||||
throw new IOException("Extra data detected in stream"); |
||||
} |
||||
|
||||
return o; |
||||
} |
||||
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 final boolean equals(ASN1Encodable other) |
||||
{ |
||||
return this == other || (null != other && asn1Equals(other.toASN1Primitive())); |
||||
} |
||||
|
||||
public final boolean equals(ASN1Primitive other) |
||||
{ |
||||
return this == other || asn1Equals(other); |
||||
} |
||||
|
||||
public final 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(); |
||||
|
||||
/** |
||||
* Return true if this objected is a CONSTRUCTED one, false otherwise. |
||||
* @return true if CONSTRUCTED bit set on object's tag, false otherwise. |
||||
*/ |
||||
abstract boolean isConstructed(); |
||||
|
||||
/** |
||||
* Return the length of the encoding this object will produce. |
||||
* @return the length of the object's encoding. |
||||
* @throws IOException if the encoding length cannot be calculated. |
||||
*/ |
||||
abstract int encodedLength() throws IOException; |
||||
|
||||
abstract void encode(ASN1OutputStream out, boolean withTag) throws IOException; |
||||
|
||||
/** |
||||
* Equality (similarity) comparison for two ASN1Primitive objects. |
||||
*/ |
||||
abstract boolean asn1Equals(ASN1Primitive o); |
||||
} |
@ -1,416 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Enumeration; |
||||
import java.util.Iterator; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* 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> |
||||
* <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. |
||||
* </p> |
||||
*/ |
||||
public abstract class ASN1Sequence |
||||
extends ASN1Primitive |
||||
implements com.fr.third.org.bouncycastle.util.Iterable<ASN1Encodable> |
||||
{ |
||||
// NOTE: Only non-final to support LazyEncodedSequence
|
||||
ASN1Encodable[] elements; |
||||
|
||||
/** |
||||
* 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 taggedObject 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 taggedObject, |
||||
boolean explicit) |
||||
{ |
||||
if (explicit) |
||||
{ |
||||
if (!taggedObject.isExplicit()) |
||||
{ |
||||
throw new IllegalArgumentException("object implicit - explicit expected."); |
||||
} |
||||
|
||||
return getInstance(taggedObject.getObject()); |
||||
} |
||||
|
||||
ASN1Primitive o = taggedObject.getObject(); |
||||
|
||||
/* |
||||
* constructed object which appears to be explicitly tagged when it should be implicit means |
||||
* we have to add the surrounding sequence. |
||||
*/ |
||||
if (taggedObject.isExplicit()) |
||||
{ |
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return new BERSequence(o); |
||||
} |
||||
|
||||
return new DLSequence(o); |
||||
} |
||||
|
||||
if (o instanceof ASN1Sequence) |
||||
{ |
||||
ASN1Sequence s = (ASN1Sequence)o; |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return s; |
||||
} |
||||
|
||||
return (ASN1Sequence)s.toDLObject(); |
||||
} |
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + taggedObject.getClass().getName()); |
||||
} |
||||
|
||||
/** |
||||
* Create an empty SEQUENCE |
||||
*/ |
||||
protected ASN1Sequence() |
||||
{ |
||||
this.elements = ASN1EncodableVector.EMPTY_ELEMENTS; |
||||
} |
||||
|
||||
/** |
||||
* Create a SEQUENCE containing one object. |
||||
* @param element the object to be put in the SEQUENCE. |
||||
*/ |
||||
protected ASN1Sequence(ASN1Encodable element) |
||||
{ |
||||
if (null == element) |
||||
{ |
||||
throw new NullPointerException("'element' cannot be null"); |
||||
} |
||||
|
||||
this.elements = new ASN1Encodable[]{ element }; |
||||
} |
||||
|
||||
/** |
||||
* Create a SEQUENCE containing a vector of objects. |
||||
* @param elementVector the vector of objects to be put in the SEQUENCE. |
||||
*/ |
||||
protected ASN1Sequence(ASN1EncodableVector elementVector) |
||||
{ |
||||
if (null == elementVector) |
||||
{ |
||||
throw new NullPointerException("'elementVector' cannot be null"); |
||||
} |
||||
|
||||
this.elements = elementVector.takeElements(); |
||||
} |
||||
|
||||
/** |
||||
* Create a SEQUENCE containing an array of objects. |
||||
* @param elements the array of objects to be put in the SEQUENCE. |
||||
*/ |
||||
protected ASN1Sequence(ASN1Encodable[] elements) |
||||
{ |
||||
if (Arrays.isNullOrContainsNull(elements)) |
||||
{ |
||||
throw new NullPointerException("'elements' cannot be null, or contain null"); |
||||
} |
||||
|
||||
this.elements = ASN1EncodableVector.cloneElements(elements); |
||||
} |
||||
|
||||
ASN1Sequence(ASN1Encodable[] elements, boolean clone) |
||||
{ |
||||
this.elements = clone ? ASN1EncodableVector.cloneElements(elements) : elements; |
||||
} |
||||
|
||||
public ASN1Encodable[] toArray() |
||||
{ |
||||
return ASN1EncodableVector.cloneElements(elements); |
||||
} |
||||
|
||||
ASN1Encodable[] toArrayInternal() |
||||
{ |
||||
return elements; |
||||
} |
||||
|
||||
public Enumeration getObjects() |
||||
{ |
||||
return new Enumeration() |
||||
{ |
||||
private int pos = 0; |
||||
|
||||
public boolean hasMoreElements() |
||||
{ |
||||
return pos < elements.length; |
||||
} |
||||
|
||||
public Object nextElement() |
||||
{ |
||||
if (pos < elements.length) |
||||
{ |
||||
return elements[pos++]; |
||||
} |
||||
throw new NoSuchElementException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public ASN1SequenceParser parser() |
||||
{ |
||||
// NOTE: Call size() here to 'force' a LazyEncodedSequence
|
||||
final int count = size(); |
||||
|
||||
return new ASN1SequenceParser() |
||||
{ |
||||
private int pos = 0; |
||||
|
||||
public ASN1Encodable readObject() throws IOException |
||||
{ |
||||
if (count == pos) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
ASN1Encodable obj = elements[pos++]; |
||||
if (obj instanceof ASN1Sequence) |
||||
{ |
||||
return ((ASN1Sequence)obj).parser(); |
||||
} |
||||
if (obj instanceof ASN1Set) |
||||
{ |
||||
return ((ASN1Set)obj).parser(); |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
public ASN1Primitive getLoadedObject() |
||||
{ |
||||
return ASN1Sequence.this; |
||||
} |
||||
|
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
return ASN1Sequence.this; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 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 elements[index]; |
||||
} |
||||
|
||||
/** |
||||
* Return the number of objects in this sequence. |
||||
* |
||||
* @return the number of objects in this sequence. |
||||
*/ |
||||
public int size() |
||||
{ |
||||
return elements.length; |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
// return Arrays.hashCode(elements);
|
||||
int i = elements.length; |
||||
int hc = i + 1; |
||||
|
||||
while (--i >= 0) |
||||
{ |
||||
hc *= 257; |
||||
hc ^= elements[i].toASN1Primitive().hashCode(); |
||||
} |
||||
|
||||
return hc; |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive other) |
||||
{ |
||||
if (!(other instanceof ASN1Sequence)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1Sequence that = (ASN1Sequence)other; |
||||
|
||||
int count = this.size(); |
||||
if (that.size() != count) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive p1 = this.elements[i].toASN1Primitive(); |
||||
ASN1Primitive p2 = that.elements[i].toASN1Primitive(); |
||||
|
||||
if (p1 != p2 && !p1.asn1Equals(p2)) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Change current SEQUENCE object to be encoded as {@link DERSequence}. |
||||
* This is part of Distinguished Encoding Rules form serialization. |
||||
*/ |
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return new DERSequence(elements, false); |
||||
} |
||||
|
||||
/** |
||||
* Change current SEQUENCE object to be encoded as {@link DLSequence}. |
||||
* This is part of Direct Length form serialization. |
||||
*/ |
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return new DLSequence(elements, false); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
abstract void encode(ASN1OutputStream out, boolean withTag) throws IOException; |
||||
|
||||
public String toString() |
||||
{ |
||||
// NOTE: Call size() here to 'force' a LazyEncodedSequence
|
||||
int count = size(); |
||||
if (0 == count) |
||||
{ |
||||
return "[]"; |
||||
} |
||||
|
||||
StringBuffer sb = new StringBuffer(); |
||||
sb.append('['); |
||||
for (int i = 0;;) |
||||
{ |
||||
sb.append(elements[i]); |
||||
if (++i >= count) |
||||
{ |
||||
break; |
||||
} |
||||
sb.append(", "); |
||||
} |
||||
sb.append(']'); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public Iterator<ASN1Encodable> iterator() |
||||
{ |
||||
return new Arrays.Iterator<ASN1Encodable>(elements); |
||||
} |
||||
} |
@ -1,19 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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; |
||||
} |
@ -1,607 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Enumeration; |
||||
import java.util.Iterator; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* 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><p> |
||||
* DER form is always definite form length fields, while |
||||
* BER support uses indefinite form. |
||||
* </p><p> |
||||
* The CER form support does not exist. |
||||
* </p><p> |
||||
* <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><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 — 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> |
||||
* <p> |
||||
* <b>8.12.1</b> The encoding of a set-of value shall be constructed. |
||||
* </p><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><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 — 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 — The padding octets are for comparison purposes only |
||||
* and do not appear in the encodings. |
||||
* </blockquote> |
||||
*/ |
||||
public abstract class ASN1Set |
||||
extends ASN1Primitive |
||||
implements com.fr.third.org.bouncycastle.util.Iterable<ASN1Encodable> |
||||
{ |
||||
protected final ASN1Encodable[] elements; |
||||
protected final boolean isSorted; |
||||
|
||||
/** |
||||
* 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 taggedObject 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 taggedObject, |
||||
boolean explicit) |
||||
{ |
||||
if (explicit) |
||||
{ |
||||
if (!taggedObject.isExplicit()) |
||||
{ |
||||
throw new IllegalArgumentException("object implicit - explicit expected."); |
||||
} |
||||
|
||||
return getInstance(taggedObject.getObject()); |
||||
} |
||||
|
||||
ASN1Primitive o = taggedObject.getObject(); |
||||
|
||||
/* |
||||
* constructed object which appears to be explicitly tagged and it's really implicit means |
||||
* we have to add the surrounding set. |
||||
*/ |
||||
if (taggedObject.isExplicit()) |
||||
{ |
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return new BERSet(o); |
||||
} |
||||
|
||||
return new DLSet(o); |
||||
} |
||||
|
||||
if (o instanceof ASN1Set) |
||||
{ |
||||
ASN1Set s = (ASN1Set)o; |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return s; |
||||
} |
||||
|
||||
return (ASN1Set)s.toDLObject(); |
||||
} |
||||
|
||||
/* |
||||
* in this case the parser returns a sequence, convert it into a set. |
||||
*/ |
||||
if (o instanceof ASN1Sequence) |
||||
{ |
||||
ASN1Sequence s = (ASN1Sequence)o; |
||||
|
||||
// NOTE: Will force() a LazyEncodedSequence
|
||||
ASN1Encodable[] elements = s.toArrayInternal(); |
||||
|
||||
if (taggedObject instanceof BERTaggedObject) |
||||
{ |
||||
return new BERSet(false, elements); |
||||
} |
||||
|
||||
return new DLSet(false, elements); |
||||
} |
||||
|
||||
throw new IllegalArgumentException("unknown object in getInstance: " + taggedObject.getClass().getName()); |
||||
} |
||||
|
||||
protected ASN1Set() |
||||
{ |
||||
this.elements = ASN1EncodableVector.EMPTY_ELEMENTS; |
||||
this.isSorted = true; |
||||
} |
||||
|
||||
/** |
||||
* Create a SET containing one object |
||||
* @param element object to be added to the SET. |
||||
*/ |
||||
protected ASN1Set(ASN1Encodable element) |
||||
{ |
||||
if (null == element) |
||||
{ |
||||
throw new NullPointerException("'element' cannot be null"); |
||||
} |
||||
|
||||
this.elements = new ASN1Encodable[]{ element }; |
||||
this.isSorted = true; |
||||
} |
||||
|
||||
/** |
||||
* Create a SET containing a vector of objects. |
||||
* @param elementVector a vector of objects to make up the SET. |
||||
* @param doSort true if should be sorted DER style, false otherwise. |
||||
*/ |
||||
protected ASN1Set(ASN1EncodableVector elementVector, boolean doSort) |
||||
{ |
||||
if (null == elementVector) |
||||
{ |
||||
throw new NullPointerException("'elementVector' cannot be null"); |
||||
} |
||||
|
||||
ASN1Encodable[] tmp; |
||||
if (doSort && elementVector.size() >= 2) |
||||
{ |
||||
tmp = elementVector.copyElements(); |
||||
sort(tmp); |
||||
} |
||||
else |
||||
{ |
||||
tmp = elementVector.takeElements(); |
||||
} |
||||
|
||||
this.elements = tmp; |
||||
this.isSorted = doSort || tmp.length < 2; |
||||
} |
||||
|
||||
/** |
||||
* Create a SET containing an array of objects. |
||||
* @param elements an array of objects to make up the SET. |
||||
* @param doSort true if should be sorted DER style, false otherwise. |
||||
*/ |
||||
protected ASN1Set(ASN1Encodable[] elements, boolean doSort) |
||||
{ |
||||
if (Arrays.isNullOrContainsNull(elements)) |
||||
{ |
||||
throw new NullPointerException("'elements' cannot be null, or contain null"); |
||||
} |
||||
|
||||
ASN1Encodable[] tmp = ASN1EncodableVector.cloneElements(elements); |
||||
if (doSort && tmp.length >= 2) |
||||
{ |
||||
sort(tmp); |
||||
} |
||||
|
||||
this.elements = tmp; |
||||
this.isSorted = doSort || tmp.length < 2; |
||||
} |
||||
|
||||
ASN1Set(boolean isSorted, ASN1Encodable[] elements) |
||||
{ |
||||
this.elements = elements; |
||||
this.isSorted = isSorted || elements.length < 2; |
||||
} |
||||
|
||||
public Enumeration getObjects() |
||||
{ |
||||
return new Enumeration() |
||||
{ |
||||
private int pos = 0; |
||||
|
||||
public boolean hasMoreElements() |
||||
{ |
||||
return pos < elements.length; |
||||
} |
||||
|
||||
public Object nextElement() |
||||
{ |
||||
if (pos < elements.length) |
||||
{ |
||||
return elements[pos++]; |
||||
} |
||||
throw new NoSuchElementException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 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 elements[index]; |
||||
} |
||||
|
||||
/** |
||||
* return the number of objects in this set. |
||||
* |
||||
* @return the number of objects in this set. |
||||
*/ |
||||
public int size() |
||||
{ |
||||
return elements.length; |
||||
} |
||||
|
||||
public ASN1Encodable[] toArray() |
||||
{ |
||||
return ASN1EncodableVector.cloneElements(elements); |
||||
} |
||||
|
||||
public ASN1SetParser parser() |
||||
{ |
||||
final int count = size(); |
||||
|
||||
return new ASN1SetParser() |
||||
{ |
||||
private int pos = 0; |
||||
|
||||
public ASN1Encodable readObject() throws IOException |
||||
{ |
||||
if (count == pos) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
ASN1Encodable obj = elements[pos++]; |
||||
if (obj instanceof ASN1Sequence) |
||||
{ |
||||
return ((ASN1Sequence)obj).parser(); |
||||
} |
||||
if (obj instanceof ASN1Set) |
||||
{ |
||||
return ((ASN1Set)obj).parser(); |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
public ASN1Primitive getLoadedObject() |
||||
{ |
||||
return ASN1Set.this; |
||||
} |
||||
|
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
return ASN1Set.this; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
// return Arrays.hashCode(elements);
|
||||
int i = elements.length; |
||||
int hc = i + 1; |
||||
|
||||
// NOTE: Order-independent contribution of elements to avoid sorting
|
||||
while (--i >= 0) |
||||
{ |
||||
hc += elements[i].toASN1Primitive().hashCode(); |
||||
} |
||||
|
||||
return hc; |
||||
} |
||||
|
||||
/** |
||||
* Change current SET object to be encoded as {@link DERSet}. |
||||
* This is part of Distinguished Encoding Rules form serialization. |
||||
*/ |
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
ASN1Encodable[] tmp; |
||||
if (isSorted) |
||||
{ |
||||
tmp = elements; |
||||
} |
||||
else |
||||
{ |
||||
tmp = (ASN1Encodable[])elements.clone(); |
||||
sort(tmp); |
||||
} |
||||
|
||||
return new DERSet(true, tmp); |
||||
} |
||||
|
||||
/** |
||||
* Change current SET object to be encoded as {@link DLSet}. |
||||
* This is part of Direct Length form serialization. |
||||
*/ |
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return new DLSet(isSorted, elements); |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive other) |
||||
{ |
||||
if (!(other instanceof ASN1Set)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1Set that = (ASN1Set)other; |
||||
|
||||
int count = this.size(); |
||||
if (that.size() != count) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERSet dis = (DERSet)this.toDERObject(); |
||||
DERSet dat = (DERSet)that.toDERObject(); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive p1 = dis.elements[i].toASN1Primitive(); |
||||
ASN1Primitive p2 = dat.elements[i].toASN1Primitive(); |
||||
|
||||
if (p1 != p2 && !p1.asn1Equals(p2)) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
abstract void encode(ASN1OutputStream out, boolean withTag) throws IOException; |
||||
|
||||
public String toString() |
||||
{ |
||||
int count = size(); |
||||
if (0 == count) |
||||
{ |
||||
return "[]"; |
||||
} |
||||
|
||||
StringBuffer sb = new StringBuffer(); |
||||
sb.append('['); |
||||
for (int i = 0;;) |
||||
{ |
||||
sb.append(elements[i]); |
||||
if (++i >= count) |
||||
{ |
||||
break; |
||||
} |
||||
sb.append(", "); |
||||
} |
||||
sb.append(']'); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public Iterator<ASN1Encodable> iterator() |
||||
{ |
||||
return new Arrays.Iterator<ASN1Encodable>(toArray()); |
||||
} |
||||
|
||||
private static byte[] getDEREncoded(ASN1Encodable obj) |
||||
{ |
||||
try |
||||
{ |
||||
return obj.toASN1Primitive().getEncoded(ASN1Encoding.DER); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new IllegalArgumentException("cannot encode object added to SET"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* return true if a <= b (arrays are assumed padded with zeros). |
||||
*/ |
||||
private static boolean lessThanOrEqual(byte[] a, byte[] b) |
||||
{ |
||||
// assert a.length >= 2 && b.length >= 2;
|
||||
|
||||
/* |
||||
* NOTE: Set elements in DER encodings are ordered first according to their tags (class and |
||||
* number); the CONSTRUCTED bit is not part of the tag. |
||||
* |
||||
* For SET-OF, this is unimportant. All elements have the same tag and DER requires them to |
||||
* either all be in constructed form or all in primitive form, according to that tag. The |
||||
* elements are effectively ordered according to their content octets. |
||||
* |
||||
* For SET, the elements will have distinct tags, and each will be in constructed or |
||||
* primitive form accordingly. Failing to ignore the CONSTRUCTED bit could therefore lead to |
||||
* ordering inversions. |
||||
*/ |
||||
int a0 = a[0] & ~BERTags.CONSTRUCTED; |
||||
int b0 = b[0] & ~BERTags.CONSTRUCTED; |
||||
if (a0 != b0) |
||||
{ |
||||
return a0 < b0; |
||||
} |
||||
|
||||
int last = Math.min(a.length, b.length) - 1; |
||||
for (int i = 1; i < last; ++i) |
||||
{ |
||||
if (a[i] != b[i]) |
||||
{ |
||||
return (a[i] & 0xFF) < (b[i] & 0xFF); |
||||
} |
||||
} |
||||
return (a[last] & 0xFF) <= (b[last] & 0xFF); |
||||
} |
||||
|
||||
private static void sort(ASN1Encodable[] t) |
||||
{ |
||||
int count = t.length; |
||||
if (count < 2) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
ASN1Encodable eh = t[0], ei = t[1]; |
||||
byte[] bh = getDEREncoded(eh), bi = getDEREncoded(ei);; |
||||
|
||||
if (lessThanOrEqual(bi, bh)) |
||||
{ |
||||
ASN1Encodable et = ei; ei = eh; eh = et; |
||||
byte[] bt = bi; bi = bh; bh = bt; |
||||
} |
||||
|
||||
for (int i = 2; i < count; ++i) |
||||
{ |
||||
ASN1Encodable e2 = t[i]; |
||||
byte[] b2 = getDEREncoded(e2); |
||||
|
||||
if (lessThanOrEqual(bi, b2)) |
||||
{ |
||||
t[i - 2] = eh; |
||||
eh = ei; bh = bi; |
||||
ei = e2; bi = b2; |
||||
continue; |
||||
} |
||||
|
||||
if (lessThanOrEqual(bh, b2)) |
||||
{ |
||||
t[i - 2] = eh; |
||||
eh = e2; bh = b2; |
||||
continue; |
||||
} |
||||
|
||||
int j = i - 1; |
||||
while (--j > 0) |
||||
{ |
||||
ASN1Encodable e1 = t[j - 1]; |
||||
byte[] b1 = getDEREncoded(e1); |
||||
|
||||
if (lessThanOrEqual(b1, b2)) |
||||
{ |
||||
break; |
||||
} |
||||
|
||||
t[j] = e1; |
||||
} |
||||
|
||||
t[j] = e2; |
||||
} |
||||
|
||||
t[count - 2] = eh; |
||||
t[count - 1] = ei; |
||||
} |
||||
} |
@ -1,19 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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; |
||||
} |
@ -1,254 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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 DLSetParser(this); |
||||
case BERTags.SEQUENCE: |
||||
return new DLSequenceParser(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); |
||||
} |
||||
} |
||||
|
||||
throw new ASN1Exception("implicit tagging not implemented"); |
||||
} |
||||
|
||||
ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException |
||||
{ |
||||
if (!constructed) |
||||
{ |
||||
// Note: !CONSTRUCTED => IMPLICIT
|
||||
DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in; |
||||
return new DLTaggedObject(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 DLTaggedObject(true, tag, v.get(0)) |
||||
: new DLTaggedObject(false, tag, DLFactory.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, |
||||
tagNo == BERTags.OCTET_STRING || tagNo == BERTags.SEQUENCE || tagNo == BERTags.SET || tagNo == BERTags.EXTERNAL); |
||||
|
||||
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, _limit); |
||||
|
||||
if ((tag & BERTags.APPLICATION) != 0) |
||||
{ |
||||
return new DLApplicationSpecific(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 DLSequenceParser(new ASN1StreamParser(defIn)); |
||||
case BERTags.SET: |
||||
return new DLSetParser(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 |
||||
{ |
||||
ASN1Encodable obj = readObject(); |
||||
if (null == obj) |
||||
{ |
||||
return new ASN1EncodableVector(0); |
||||
} |
||||
|
||||
ASN1EncodableVector v = new ASN1EncodableVector(); |
||||
do |
||||
{ |
||||
if (obj instanceof InMemoryRepresentable) |
||||
{ |
||||
v.add(((InMemoryRepresentable)obj).getLoadedObject()); |
||||
} |
||||
else |
||||
{ |
||||
v.add(obj.toASN1Primitive()); |
||||
} |
||||
} |
||||
while ((obj = readObject()) != null); |
||||
return v; |
||||
} |
||||
} |
@ -1,13 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
/** |
||||
* General interface implemented by ASN.1 STRING objects for extracting the content String. |
||||
*/ |
||||
public interface ASN1String |
||||
{ |
||||
/** |
||||
* Return a Java String representation of this STRING type's content. |
||||
* @return a Java String representation of this STRING. |
||||
*/ |
||||
public String getString(); |
||||
} |
@ -1,187 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by |
||||
* a [n] where n is some number - these are assumed to follow the construction |
||||
* rules (as with sequences). |
||||
*/ |
||||
public abstract class ASN1TaggedObject |
||||
extends ASN1Primitive |
||||
implements ASN1TaggedObjectParser |
||||
{ |
||||
final int tagNo; |
||||
final boolean explicit; |
||||
final ASN1Encodable obj; |
||||
|
||||
static public ASN1TaggedObject getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
if (explicit) |
||||
{ |
||||
return getInstance(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 (null == obj) |
||||
{ |
||||
throw new NullPointerException("'obj' cannot be null"); |
||||
} |
||||
|
||||
this.tagNo = tagNo; |
||||
this.explicit = explicit || (obj instanceof ASN1Choice); |
||||
this.obj = obj; |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive other) |
||||
{ |
||||
if (!(other instanceof ASN1TaggedObject)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1TaggedObject that = (ASN1TaggedObject)other; |
||||
|
||||
if (this.tagNo != that.tagNo || this.explicit != that.explicit) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
ASN1Primitive p1 = this.obj.toASN1Primitive(); |
||||
ASN1Primitive p2 = that.obj.toASN1Primitive(); |
||||
|
||||
return p1 == p2 || p1.asn1Equals(p2); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return tagNo ^ (explicit ? 0x0F : 0xF0) ^ obj.toASN1Primitive().hashCode(); |
||||
} |
||||
|
||||
/** |
||||
* Return the tag number associated with this object. |
||||
* |
||||
* @return the tag number. |
||||
*/ |
||||
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; |
||||
} |
||||
|
||||
/** |
||||
* 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() |
||||
{ |
||||
return obj.toASN1Primitive(); |
||||
} |
||||
|
||||
/** |
||||
* 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) |
||||
throws IOException |
||||
{ |
||||
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 ASN1Exception("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, boolean withTag) throws IOException; |
||||
|
||||
public String toString() |
||||
{ |
||||
return "[" + tagNo + "]" + obj; |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Interface for the parsing of a generic tagged ASN.1 object. |
||||
*/ |
||||
public interface ASN1TaggedObjectParser |
||||
extends ASN1Encodable, InMemoryRepresentable |
||||
{ |
||||
/** |
||||
* Return the tag number associated with the underlying tagged object. |
||||
* @return the object's tag number. |
||||
*/ |
||||
int getTagNo(); |
||||
|
||||
/** |
||||
* Return a parser for the actual object tagged. |
||||
* |
||||
* @param tag the primitive tag value for the object tagged originally. |
||||
* @param isExplicit true if the tagging was done explicitly. |
||||
* @return a parser for the tagged object. |
||||
* @throws IOException if a parser cannot be constructed. |
||||
*/ |
||||
ASN1Encodable getObjectParser(int tag, boolean isExplicit) |
||||
throws IOException; |
||||
} |
@ -1,316 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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 com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.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.getInstance(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'", DateUtil.EN_Locale); |
||||
|
||||
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) |
||||
{ |
||||
if (time.length < 2) |
||||
{ |
||||
throw new IllegalArgumentException("UTCTime string too short"); |
||||
} |
||||
this.time = time; |
||||
if (!(isDigit(0) && isDigit(1))) |
||||
{ |
||||
throw new IllegalArgumentException("illegal characters in UTCTime string"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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 DateUtil.epochAdjust(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 DateUtil.epochAdjust(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; |
||||
} |
||||
} |
||||
|
||||
private boolean isDigit(int pos) |
||||
{ |
||||
return time.length > pos && time[pos] >= '0' && time[pos] <= '9'; |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
int length = time.length; |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.UTC_TIME, time); |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
@ -1,110 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* An indefinite-length encoding version of an ASN.1 ApplicationSpecific object. |
||||
*/ |
||||
public class BERApplicationSpecific |
||||
extends ASN1ApplicationSpecific |
||||
{ |
||||
BERApplicationSpecific( |
||||
boolean isConstructed, |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
super(isConstructed, tag, octets); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with a tagging of explicit/constructed. |
||||
* |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public BERApplicationSpecific( |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
this(true, tag, object); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with the tagging style given by the value of constructed. |
||||
* |
||||
* @param constructed true if the object is constructed. |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public BERApplicationSpecific( |
||||
boolean constructed, |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object)); |
||||
} |
||||
|
||||
private static byte[] getEncoding(boolean explicit, ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.BER); |
||||
|
||||
if (explicit) |
||||
{ |
||||
return data; |
||||
} |
||||
else |
||||
{ |
||||
int lenBytes = getLengthOfHeader(data); |
||||
byte[] tmp = new byte[data.length - lenBytes]; |
||||
System.arraycopy(data, lenBytes, tmp, 0, tmp.length); |
||||
return tmp; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object which is marked as constructed |
||||
* |
||||
* @param tagNo the tag number for this object. |
||||
* @param vec the objects making up the application specific object. |
||||
*/ |
||||
public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec) |
||||
{ |
||||
super(true, tagNo, getEncodedVector(vec)); |
||||
} |
||||
|
||||
private static byte[] getEncodedVector(ASN1EncodableVector vec) |
||||
{ |
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
||||
|
||||
for (int i = 0; i != vec.size(); i++) |
||||
{ |
||||
try |
||||
{ |
||||
bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.BER)); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("malformed object: " + e, e); |
||||
} |
||||
} |
||||
return bOut.toByteArray(); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
int flags = BERTags.APPLICATION; |
||||
if (isConstructed) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeEncodedIndef(withTag, flags, tag, octets); |
||||
} |
||||
} |
@ -1,59 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A parser for indefinite-length ASN.1 ApplicationSpecific objects. |
||||
*/ |
||||
public class BERApplicationSpecificParser |
||||
implements ASN1ApplicationSpecificParser |
||||
{ |
||||
private final int tag; |
||||
private final ASN1StreamParser parser; |
||||
|
||||
BERApplicationSpecificParser(int tag, ASN1StreamParser parser) |
||||
{ |
||||
this.tag = tag; |
||||
this.parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Return the object contained in this application specific object, |
||||
* @return the contained object. |
||||
* @throws IOException if the underlying stream cannot be read, or does not contain an ASN.1 encoding. |
||||
*/ |
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the application specific object. |
||||
* |
||||
* @return a BERApplicationSpecific. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new BERApplicationSpecific(tag, parser.readVector()); |
||||
} |
||||
|
||||
/** |
||||
* Return a BERApplicationSpecific representing this parser and its contents. |
||||
* |
||||
* @return a BERApplicationSpecific |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
class BERFactory |
||||
{ |
||||
static final BERSequence EMPTY_SEQUENCE = new BERSequence(); |
||||
static final BERSet EMPTY_SET = new BERSet(); |
||||
|
||||
static BERSequence createSequence(ASN1EncodableVector v) |
||||
{ |
||||
if (v.size() < 1) |
||||
{ |
||||
return EMPTY_SEQUENCE; |
||||
} |
||||
|
||||
return new BERSequence(v); |
||||
} |
||||
|
||||
static BERSet createSet(ASN1EncodableVector v) |
||||
{ |
||||
if (v.size() < 1) |
||||
{ |
||||
return EMPTY_SET; |
||||
} |
||||
|
||||
return new BERSet(v); |
||||
} |
||||
} |
@ -1,82 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Base class for generators for indefinite-length structures. |
||||
*/ |
||||
public class BERGenerator |
||||
extends ASN1Generator |
||||
{ |
||||
private boolean _tagged = false; |
||||
private boolean _isExplicit; |
||||
private int _tagNo; |
||||
|
||||
protected BERGenerator(OutputStream out) |
||||
{ |
||||
super(out); |
||||
} |
||||
|
||||
protected BERGenerator(OutputStream out, int tagNo, boolean isExplicit) |
||||
{ |
||||
super(out); |
||||
|
||||
// TODO Check proper handling of implicit tagging
|
||||
_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 writeBEREnd() throws IOException |
||||
{ |
||||
_out.write(0x00); |
||||
_out.write(0x00); |
||||
|
||||
if (_tagged && _isExplicit) // write extra end for tag header
|
||||
{ |
||||
_out.write(0x00); |
||||
_out.write(0x00); |
||||
} |
||||
} |
||||
} |
@ -1,193 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.util.Enumeration; |
||||
import java.util.NoSuchElementException; |
||||
|
||||
/** |
||||
* ASN.1 OctetStrings, with indefinite length rules, and <i>constructed form</i> support. |
||||
* <p> |
||||
* The Basic Encoding Rules (BER) format allows encoding using so called "<i>constructed form</i>", |
||||
* which DER and CER formats forbid allowing only "primitive form". |
||||
* </p><p> |
||||
* This class <b>always</b> produces the constructed form with underlying segments |
||||
* in an indefinite length array. If the input wasn't the same, then this output |
||||
* is not faithful reproduction. |
||||
* </p> |
||||
* <p> |
||||
* See {@link ASN1OctetString} for X.690 encoding rules of OCTET-STRING objects. |
||||
* </p> |
||||
*/ |
||||
public class BEROctetString |
||||
extends ASN1OctetString |
||||
{ |
||||
private static final int DEFAULT_CHUNK_SIZE = 1000; |
||||
|
||||
private final int chunkSize; |
||||
private final 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 |
||||
{ |
||||
bOut.write(octs[i].getOctets()); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new IllegalArgumentException("exception converting octets " + e.toString()); |
||||
} |
||||
} |
||||
|
||||
return bOut.toByteArray(); |
||||
} |
||||
|
||||
/** |
||||
* Create an OCTET-STRING object from a byte[] |
||||
* @param string the octets making up the octet string. |
||||
*/ |
||||
public BEROctetString( |
||||
byte[] string) |
||||
{ |
||||
this(string, DEFAULT_CHUNK_SIZE); |
||||
} |
||||
|
||||
/** |
||||
* Multiple {@link ASN1OctetString} data blocks are input, |
||||
* the result is <i>constructed form</i>. |
||||
* |
||||
* @param octs an array of OCTET STRING to construct the BER OCTET STRING from. |
||||
*/ |
||||
public BEROctetString( |
||||
ASN1OctetString[] octs) |
||||
{ |
||||
this(octs, DEFAULT_CHUNK_SIZE); |
||||
} |
||||
|
||||
/** |
||||
* Create an OCTET-STRING object from a byte[] |
||||
* @param string the octets making up the octet string. |
||||
* @param chunkSize the number of octets stored in each DER encoded component OCTET STRING. |
||||
*/ |
||||
public BEROctetString( |
||||
byte[] string, |
||||
int chunkSize) |
||||
{ |
||||
this(string, null, chunkSize); |
||||
} |
||||
|
||||
/** |
||||
* Multiple {@link ASN1OctetString} data blocks are input, |
||||
* the result is <i>constructed form</i>. |
||||
* |
||||
* @param octs an array of OCTET STRING to construct the BER OCTET STRING from. |
||||
* @param chunkSize the number of octets stored in each DER encoded component OCTET STRING. |
||||
*/ |
||||
public BEROctetString( |
||||
ASN1OctetString[] octs, |
||||
int chunkSize) |
||||
{ |
||||
this(toBytes(octs), octs, chunkSize); |
||||
} |
||||
|
||||
private BEROctetString(byte[] string, ASN1OctetString[] octs, int chunkSize) |
||||
{ |
||||
super(string); |
||||
this.octs = octs; |
||||
this.chunkSize = chunkSize; |
||||
} |
||||
|
||||
/** |
||||
* Return the OCTET STRINGs that make up this string. |
||||
* |
||||
* @return an Enumeration of the component OCTET STRINGs. |
||||
*/ |
||||
public Enumeration getObjects() |
||||
{ |
||||
if (octs == null) |
||||
{ |
||||
return new Enumeration() |
||||
{ |
||||
int pos = 0; |
||||
|
||||
public boolean hasMoreElements() |
||||
{ |
||||
return pos < string.length; |
||||
} |
||||
|
||||
public Object nextElement() |
||||
{ |
||||
if (pos < string.length) |
||||
{ |
||||
int length = Math.min(string.length - pos, chunkSize); |
||||
byte[] chunk = new byte[length]; |
||||
System.arraycopy(string, pos, chunk, 0, length); |
||||
pos += length; |
||||
return new DEROctetString(chunk); |
||||
} |
||||
throw new NoSuchElementException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
return new Enumeration() |
||||
{ |
||||
int counter = 0; |
||||
|
||||
public boolean hasMoreElements() |
||||
{ |
||||
return counter < octs.length; |
||||
} |
||||
|
||||
public Object nextElement() |
||||
{ |
||||
if (counter < octs.length) |
||||
{ |
||||
return octs[counter++]; |
||||
} |
||||
throw new NoSuchElementException(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncodedIndef(withTag, BERTags.CONSTRUCTED | BERTags.OCTET_STRING, getObjects()); |
||||
} |
||||
|
||||
static BEROctetString fromSequence(ASN1Sequence seq) |
||||
{ |
||||
int count = seq.size(); |
||||
ASN1OctetString[] v = new ASN1OctetString[count]; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
v[i] = ASN1OctetString.getInstance(seq.getObjectAt(i)); |
||||
} |
||||
return new BEROctetString(v); |
||||
} |
||||
} |
@ -1,131 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* A generator for indefinite-length OCTET STRINGs |
||||
*/ |
||||
public class BEROctetStringGenerator |
||||
extends BERGenerator |
||||
{ |
||||
/** |
||||
* Use the passed in stream as the target for the generator, writing out the header tag |
||||
* for a constructed OCTET STRING. |
||||
* |
||||
* @param out target stream |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public BEROctetStringGenerator(OutputStream out) |
||||
throws IOException |
||||
{ |
||||
super(out); |
||||
|
||||
writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING); |
||||
} |
||||
|
||||
/** |
||||
* Use the passed in stream as the target for the generator, writing out the header tag |
||||
* for a tagged constructed OCTET STRING (possibly implicit). |
||||
* |
||||
* @param out target stream |
||||
* @param tagNo the tag number to introduce |
||||
* @param isExplicit true if this is an explicitly tagged object, false otherwise. |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public BEROctetStringGenerator( |
||||
OutputStream out, |
||||
int tagNo, |
||||
boolean isExplicit) |
||||
throws IOException |
||||
{ |
||||
super(out, tagNo, isExplicit); |
||||
|
||||
writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING); |
||||
} |
||||
|
||||
/** |
||||
* Return a stream representing the content target for this OCTET STRING |
||||
* |
||||
* @return an OutputStream which chunks data in blocks of 1000 (CER limit). |
||||
*/ |
||||
public OutputStream getOctetOutputStream() |
||||
{ |
||||
return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
|
||||
} |
||||
|
||||
/** |
||||
* Return a stream representing the content target for this OCTET STRING |
||||
* |
||||
* @param buf the buffer to use for chunking the data. |
||||
* @return an OutputStream which chunks data in blocks of buf length. |
||||
*/ |
||||
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, true, _buf, 0, _buf.length); |
||||
_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, true, _buf, 0, _buf.length); |
||||
_off = 0; |
||||
|
||||
off += numToCopy; |
||||
len -= numToCopy; |
||||
} |
||||
} |
||||
|
||||
public void close() |
||||
throws IOException |
||||
{ |
||||
if (_off != 0) |
||||
{ |
||||
DEROctetString.encode(_derOut, true, _buf, 0, _off); |
||||
} |
||||
|
||||
_derOut.flushInternal(); |
||||
|
||||
writeBEREnd(); |
||||
} |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.io.Streams; |
||||
|
||||
/** |
||||
* A parser for indefinite-length OCTET STRINGs. |
||||
*/ |
||||
public class BEROctetStringParser |
||||
implements ASN1OctetStringParser |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
BEROctetStringParser( |
||||
ASN1StreamParser parser) |
||||
{ |
||||
_parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Return an InputStream representing the contents of the OCTET STRING. |
||||
* |
||||
* @return an InputStream with its source as the OCTET STRING content. |
||||
*/ |
||||
public InputStream getOctetStream() |
||||
{ |
||||
return new ConstructedOctetStream(_parser); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the OCTET STRING. |
||||
* |
||||
* @return a BEROctetString. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new BEROctetString(Streams.readAll(getOctetStream())); |
||||
} |
||||
|
||||
/** |
||||
* Return an BEROctetString representing this parser and its contents. |
||||
* |
||||
* @return an BEROctetString |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -1,22 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* A class which writes indefinite and definite length objects. Objects which specify DER will be |
||||
* encoded accordingly, but DL or BER objects will be encoded as defined. |
||||
*/ |
||||
class BEROutputStream |
||||
extends ASN1OutputStream |
||||
{ |
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @param os |
||||
* target output stream. |
||||
*/ |
||||
BEROutputStream(OutputStream os) |
||||
{ |
||||
super(os); |
||||
} |
||||
} |
@ -1,65 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Indefinite length SEQUENCE of objects. |
||||
* <p> |
||||
* Length field has value 0x80, and the sequence ends with two bytes of: 0x00, 0x00. |
||||
* </p><p> |
||||
* For X.690 syntax rules, see {@link ASN1Sequence}. |
||||
* </p> |
||||
*/ |
||||
public class BERSequence |
||||
extends ASN1Sequence |
||||
{ |
||||
/** |
||||
* Create an empty sequence |
||||
*/ |
||||
public BERSequence() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing one object |
||||
*/ |
||||
public BERSequence(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing a vector of objects. |
||||
*/ |
||||
public BERSequence(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector); |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing an array of objects. |
||||
*/ |
||||
public BERSequence(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements); |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive p = elements[i].toASN1Primitive(); |
||||
totalLength += p.encodedLength(); |
||||
} |
||||
|
||||
return 2 + totalLength + 2; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncodedIndef(withTag, BERTags.SEQUENCE | BERTags.CONSTRUCTED, elements); |
||||
} |
||||
} |
@ -1,71 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* A stream generator for DER SEQUENCEs |
||||
*/ |
||||
public class BERSequenceGenerator |
||||
extends BERGenerator |
||||
{ |
||||
/** |
||||
* Use the passed in stream as the target for the generator, writing out the header tag |
||||
* for a constructed SEQUENCE. |
||||
* |
||||
* @param out target stream |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public BERSequenceGenerator( |
||||
OutputStream out) |
||||
throws IOException |
||||
{ |
||||
super(out); |
||||
|
||||
writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE); |
||||
} |
||||
|
||||
/** |
||||
* Use the passed in stream as the target for the generator, writing out the header tag |
||||
* for a tagged constructed SEQUENCE (possibly implicit). |
||||
* |
||||
* @param out target stream |
||||
* @param tagNo the tag number to introduce |
||||
* @param isExplicit true if this is an explicitly tagged object, false otherwise. |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public BERSequenceGenerator( |
||||
OutputStream out, |
||||
int tagNo, |
||||
boolean isExplicit) |
||||
throws IOException |
||||
{ |
||||
super(out, tagNo, isExplicit); |
||||
|
||||
writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE); |
||||
} |
||||
|
||||
/** |
||||
* Add an object to the SEQUENCE being generated. |
||||
* |
||||
* @param object an ASN.1 encodable object to add. |
||||
* @throws IOException if the target stream cannot be written to or the object cannot be encoded. |
||||
*/ |
||||
public void addObject( |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
object.toASN1Primitive().encodeTo(_out); |
||||
} |
||||
|
||||
/** |
||||
* Close of the generator, writing out the BER end tag. |
||||
* |
||||
* @throws IOException if the target stream cannot be written. |
||||
*/ |
||||
public void close() |
||||
throws IOException |
||||
{ |
||||
writeBEREnd(); |
||||
} |
||||
} |
@ -1,58 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser for indefinite-length SEQUENCEs. |
||||
*/ |
||||
public class BERSequenceParser |
||||
implements ASN1SequenceParser |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
BERSequenceParser(ASN1StreamParser parser) |
||||
{ |
||||
this._parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Read the next object in the SEQUENCE. |
||||
* |
||||
* @return the next object in the SEQUENCE, null if there are no more. |
||||
* @throws IOException if there is an issue reading the underlying stream. |
||||
*/ |
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the SEQUENCE. |
||||
* |
||||
* @return a BERSequence. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new BERSequence(_parser.readVector()); |
||||
} |
||||
|
||||
/** |
||||
* Return an BERSequence representing this parser and its contents. |
||||
* |
||||
* @return an BERSequence |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new IllegalStateException(e.getMessage()); |
||||
} |
||||
} |
||||
} |
@ -1,80 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Indefinite length <code>SET</code> and <code>SET OF</code> constructs. |
||||
* <p> |
||||
* Note: This does not know which syntax the set is! |
||||
* </p><p> |
||||
* Length field has value 0x80, and the set ends with two bytes of: 0x00, 0x00. |
||||
* </p><p> |
||||
* For X.690 syntax rules, see {@link ASN1Set}. |
||||
* </p><p> |
||||
* In brief: Constructing this form does not sort the supplied elements, |
||||
* nor does the sorting happen before serialization. This is different |
||||
* from the way {@link DERSet} does things. |
||||
* </p> |
||||
*/ |
||||
public class BERSet |
||||
extends ASN1Set |
||||
{ |
||||
/** |
||||
* Create an empty SET. |
||||
*/ |
||||
public BERSet() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Create a SET containing one object. |
||||
* |
||||
* @param element - a single object that makes up the set. |
||||
*/ |
||||
public BERSet(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* Create a SET containing multiple objects. |
||||
* @param elementVector a vector of objects making up the set. |
||||
*/ |
||||
public BERSet(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector, false); |
||||
} |
||||
|
||||
/** |
||||
* Create a SET from an array of objects. |
||||
* @param elements an array of ASN.1 objects. |
||||
*/ |
||||
public BERSet(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements, false); |
||||
} |
||||
|
||||
BERSet(boolean isSorted, ASN1Encodable[] elements) |
||||
{ |
||||
super(isSorted, elements); |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive p = elements[i].toASN1Primitive(); |
||||
totalLength += p.encodedLength(); |
||||
} |
||||
|
||||
return 2 + totalLength + 2; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncodedIndef(withTag, BERTags.SET | BERTags.CONSTRUCTED, elements); |
||||
} |
||||
} |
@ -1,58 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser for indefinite-length SETs. |
||||
*/ |
||||
public class BERSetParser |
||||
implements ASN1SetParser |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
BERSetParser(ASN1StreamParser parser) |
||||
{ |
||||
this._parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Read the next object in the SET. |
||||
* |
||||
* @return the next object in the SET, null if there are no more. |
||||
* @throws IOException if there is an issue reading the underlying stream. |
||||
*/ |
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the SET. |
||||
* |
||||
* @return a BERSet. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new BERSet(_parser.readVector()); |
||||
} |
||||
|
||||
/** |
||||
* Return an BERSet representing this parser and its contents. |
||||
* |
||||
* @return an BERSet |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -1,138 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Enumeration; |
||||
|
||||
/** |
||||
* BER TaggedObject - in ASN.1 notation this is any object preceded by |
||||
* a [n] where n is some number - these are assumed to follow the construction |
||||
* rules (as with sequences). |
||||
*/ |
||||
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() |
||||
{ |
||||
return explicit || obj.toASN1Primitive().isConstructed(); |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
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; |
||||
} |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeTag(withTag, BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo); |
||||
out.write(0x80); |
||||
|
||||
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 ASN1Exception("not implemented: " + obj.getClass().getName()); |
||||
} |
||||
|
||||
out.writeElements(e); |
||||
} |
||||
else |
||||
{ |
||||
out.writePrimitive(obj.toASN1Primitive(), true); |
||||
} |
||||
|
||||
out.write(0x00); |
||||
out.write(0x00); |
||||
|
||||
// ASN1Primitive primitive = obj.toASN1Primitive();
|
||||
//
|
||||
// int flags = BERTags.TAGGED;
|
||||
// if (explicit || primitive.isConstructed())
|
||||
// {
|
||||
// flags |= BERTags.CONSTRUCTED;
|
||||
// }
|
||||
//
|
||||
// out.writeTag(withTag, flags, tagNo);
|
||||
//
|
||||
// if (explicit)
|
||||
// {
|
||||
// out.write(0x80);
|
||||
// out.writePrimitive(obj.toASN1Primitive(), true);
|
||||
// out.write(0x00);
|
||||
// out.write(0x00);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// out.writePrimitive(obj.toASN1Primitive(), false);
|
||||
// }
|
||||
} |
||||
} |
@ -1,98 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser for indefinite-length tagged objects. |
||||
*/ |
||||
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; |
||||
} |
||||
|
||||
/** |
||||
* Return true if this tagged object is marked as constructed. |
||||
* |
||||
* @return true if constructed, false otherwise. |
||||
*/ |
||||
public boolean isConstructed() |
||||
{ |
||||
return _constructed; |
||||
} |
||||
|
||||
/** |
||||
* Return the tag number associated with this object. |
||||
* |
||||
* @return the tag number. |
||||
*/ |
||||
public int getTagNo() |
||||
{ |
||||
return _tagNumber; |
||||
} |
||||
|
||||
/** |
||||
* Return an object parser for the contents of this tagged object. |
||||
* |
||||
* @param tag the actual tag number of the object (needed if implicit). |
||||
* @param isExplicit true if the contained object was explicitly tagged, false if implicit. |
||||
* @return an ASN.1 encodable object parser. |
||||
* @throws IOException if there is an issue building the object parser from the stream. |
||||
*/ |
||||
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); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the tagged object. |
||||
* |
||||
* @return an ASN1TaggedObject. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readTaggedObject(_constructed, _tagNumber); |
||||
} |
||||
|
||||
/** |
||||
* Return an ASN1TaggedObject representing this parser and its contents. |
||||
* |
||||
* @return an ASN1TaggedObject |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return this.getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException(e.getMessage()); |
||||
} |
||||
} |
||||
} |
@ -1,36 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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; // decimal 10
|
||||
public static final int SEQUENCE = 0x10; // decimal 16
|
||||
public static final int SEQUENCE_OF = 0x10; // for completeness - used to model a SEQUENCE of the same type.
|
||||
public static final int SET = 0x11; // decimal 17
|
||||
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; // decimal 18
|
||||
public static final int PRINTABLE_STRING = 0x13; // decimal 19
|
||||
public static final int T61_STRING = 0x14; // decimal 20
|
||||
public static final int VIDEOTEX_STRING = 0x15; // decimal 21
|
||||
public static final int IA5_STRING = 0x16; // decimal 22
|
||||
public static final int UTC_TIME = 0x17; // decimal 23
|
||||
public static final int GENERALIZED_TIME = 0x18; // decimal 24
|
||||
public static final int GRAPHIC_STRING = 0x19; // decimal 25
|
||||
public static final int VISIBLE_STRING = 0x1a; // decimal 26
|
||||
public static final int GENERAL_STRING = 0x1b; // decimal 27
|
||||
public static final int UNIVERSAL_STRING = 0x1c; // decimal 28
|
||||
public static final int BMP_STRING = 0x1e; // decimal 30
|
||||
public static final int UTF8_STRING = 0x0c; // decimal 12
|
||||
|
||||
public static final int CONSTRUCTED = 0x20; // decimal 32
|
||||
public static final int APPLICATION = 0x40; // decimal 64
|
||||
public static final int TAGGED = 0x80; // decimal 128
|
||||
} |
@ -1,123 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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 next = getNextParser(); |
||||
if (next == null) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
_first = false; |
||||
_currentStream = next.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 next = getNextParser(); |
||||
if (next == null) |
||||
{ |
||||
_currentStream = null; |
||||
return totalRead < 1 ? -1 : totalRead; |
||||
} |
||||
|
||||
_currentStream = next.getOctetStream(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int read() |
||||
throws IOException |
||||
{ |
||||
if (_currentStream == null) |
||||
{ |
||||
if (!_first) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
ASN1OctetStringParser next = getNextParser(); |
||||
if (next == null) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
_first = false; |
||||
_currentStream = next.getOctetStream(); |
||||
} |
||||
|
||||
for (;;) |
||||
{ |
||||
int b = _currentStream.read(); |
||||
|
||||
if (b >= 0) |
||||
{ |
||||
return b; |
||||
} |
||||
|
||||
ASN1OctetStringParser next = getNextParser(); |
||||
if (next == null) |
||||
{ |
||||
_currentStream = null; |
||||
return -1; |
||||
} |
||||
|
||||
_currentStream = next.getOctetStream(); |
||||
} |
||||
} |
||||
|
||||
private ASN1OctetStringParser getNextParser() throws IOException |
||||
{ |
||||
ASN1Encodable asn1Obj = _parser.readObject(); |
||||
if (asn1Obj == null) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
if (asn1Obj instanceof ASN1OctetStringParser) |
||||
{ |
||||
return (ASN1OctetStringParser)asn1Obj; |
||||
} |
||||
|
||||
throw new IOException("unknown object encountered: " + asn1Obj.getClass()); |
||||
} |
||||
} |
@ -1,124 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A DER encoding version of an application specific object. |
||||
*/ |
||||
public class DERApplicationSpecific |
||||
extends ASN1ApplicationSpecific |
||||
{ |
||||
DERApplicationSpecific( |
||||
boolean isConstructed, |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
super(isConstructed, tag, octets); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object from the passed in data. This will assume |
||||
* the data does not represent a constructed object. |
||||
* |
||||
* @param tag the tag number for this object. |
||||
* @param octets the encoding of the object's body. |
||||
*/ |
||||
public DERApplicationSpecific( |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
this(false, tag, octets); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with a tagging of explicit/constructed. |
||||
* |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public DERApplicationSpecific( |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
this(true, tag, object); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with the tagging style given by the value of constructed. |
||||
* |
||||
* @param constructed true if the object is constructed. |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public DERApplicationSpecific( |
||||
boolean constructed, |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object)); |
||||
} |
||||
|
||||
private static byte[] getEncoding(boolean explicit, ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.DER); |
||||
|
||||
if (explicit) |
||||
{ |
||||
return data; |
||||
} |
||||
else |
||||
{ |
||||
int lenBytes = getLengthOfHeader(data); |
||||
byte[] tmp = new byte[data.length - lenBytes]; |
||||
System.arraycopy(data, lenBytes, tmp, 0, tmp.length); |
||||
return tmp; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object which is marked as constructed |
||||
* |
||||
* @param tagNo the tag number for this object. |
||||
* @param vec the objects making up the application specific object. |
||||
*/ |
||||
public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec) |
||||
{ |
||||
super(true, tagNo, getEncodedVector(vec)); |
||||
} |
||||
|
||||
private static byte[] getEncodedVector(ASN1EncodableVector vec) |
||||
{ |
||||
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); |
||||
} |
||||
} |
||||
return bOut.toByteArray(); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
int flags = BERTags.APPLICATION; |
||||
if (isConstructed) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeEncoded(withTag, flags, tag, octets); |
||||
} |
||||
} |
@ -1,215 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* DER BMPString object encodes BMP (<i>Basic Multilingual Plane</i>) subset |
||||
* (aka UCS-2) of UNICODE (ISO 10646) characters in codepoints 0 to 65535. |
||||
* <p> |
||||
* At ISO-10646:2011 the term "BMP" has been withdrawn, and replaced by |
||||
* term "UCS-2". |
||||
* </p> |
||||
*/ |
||||
public class DERBMPString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final 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) |
||||
{ |
||||
if (string == null) |
||||
{ |
||||
throw new NullPointerException("'string' cannot be null"); |
||||
} |
||||
|
||||
int byteLen = string.length; |
||||
if (0 != (byteLen & 1)) |
||||
{ |
||||
throw new IllegalArgumentException("malformed BMPString encoding encountered"); |
||||
} |
||||
|
||||
int charLen = byteLen / 2; |
||||
char[] cs = new char[charLen]; |
||||
|
||||
for (int i = 0; i != charLen; i++) |
||||
{ |
||||
cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff)); |
||||
} |
||||
|
||||
this.string = cs; |
||||
} |
||||
|
||||
DERBMPString(char[] string) |
||||
{ |
||||
if (string == null) |
||||
{ |
||||
throw new NullPointerException("'string' cannot be null"); |
||||
} |
||||
|
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor |
||||
* @param string a String to wrap as a BMP STRING. |
||||
*/ |
||||
public DERBMPString( |
||||
String string) |
||||
{ |
||||
if (string == null) |
||||
{ |
||||
throw new NullPointerException("'string' cannot be null"); |
||||
} |
||||
|
||||
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, boolean withTag) |
||||
throws IOException |
||||
{ |
||||
int count = string.length; |
||||
if (withTag) |
||||
{ |
||||
out.write(BERTags.BMP_STRING); |
||||
} |
||||
out.writeLength(count * 2); |
||||
|
||||
byte[] buf = new byte[8]; |
||||
|
||||
int i = 0, limit = count & -4; |
||||
while (i < limit) |
||||
{ |
||||
char c0 = string[i], c1 = string[i + 1], c2 = string[i + 2], c3 = string[i + 3]; |
||||
i += 4; |
||||
|
||||
buf[0] = (byte)(c0 >> 8); |
||||
buf[1] = (byte)c0; |
||||
buf[2] = (byte)(c1 >> 8); |
||||
buf[3] = (byte)c1; |
||||
buf[4] = (byte)(c2 >> 8); |
||||
buf[5] = (byte)c2; |
||||
buf[6] = (byte)(c3 >> 8); |
||||
buf[7] = (byte)c3; |
||||
|
||||
out.write(buf, 0, 8); |
||||
} |
||||
if (i < count) |
||||
{ |
||||
int bufPos = 0; |
||||
do |
||||
{ |
||||
char c0 = string[i]; |
||||
i += 1; |
||||
|
||||
buf[bufPos++] = (byte)(c0 >> 8); |
||||
buf[bufPos++] = (byte)c0; |
||||
} |
||||
while (i < count); |
||||
|
||||
out.write(buf, 0, bufPos); |
||||
} |
||||
} |
||||
} |
@ -1,158 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A BIT STRING with DER encoding - the first byte contains the count of padding bits included in the byte array's last byte. |
||||
*/ |
||||
public class DERBitString |
||||
extends ASN1BitString |
||||
{ |
||||
/** |
||||
* 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; |
||||
} |
||||
if (obj instanceof DLBitString) |
||||
{ |
||||
return new DERBitString(((DLBitString)obj).data, ((DLBitString)obj).padBits); |
||||
} |
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERBitString)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 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.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
protected DERBitString(byte data, int padBits) |
||||
{ |
||||
super(data, 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) |
||||
{ |
||||
super(data, padBits); |
||||
} |
||||
|
||||
public DERBitString( |
||||
byte[] data) |
||||
{ |
||||
this(data, 0); |
||||
} |
||||
|
||||
public DERBitString( |
||||
int value) |
||||
{ |
||||
super(getBytes(value), getPadBits(value)); |
||||
} |
||||
|
||||
public DERBitString( |
||||
ASN1Encodable obj) |
||||
throws IOException |
||||
{ |
||||
super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
int len = data.length; |
||||
if (0 == len |
||||
|| 0 == padBits |
||||
|| (data[len - 1] == (byte)(data[len - 1] & (0xFF << padBits)))) |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.BIT_STRING, (byte)padBits, data); |
||||
} |
||||
else |
||||
{ |
||||
byte der = (byte)(data[len - 1] & (0xFF << padBits)); |
||||
out.writeEncoded(withTag, BERTags.BIT_STRING, (byte)padBits, data, 0, len - 1, der); |
||||
} |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
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); |
||||
} |
||||
} |
@ -1,95 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Class representing the DER-type External |
||||
*/ |
||||
public class DERExternal |
||||
extends ASN1External |
||||
{ |
||||
/** |
||||
* Construct a DER EXTERNAL object, the input encoding vector must have exactly two elements on it. |
||||
* <p> |
||||
* Acceptable input formats are: |
||||
* <ul> |
||||
* <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li> |
||||
* <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li> |
||||
* <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li> |
||||
* </ul> |
||||
* |
||||
* @throws IllegalArgumentException if input size is wrong, or |
||||
*/ |
||||
public DERExternal(ASN1EncodableVector vector) |
||||
{ |
||||
super(vector); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of DERExternal |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param externalData The external data in its encoded form. |
||||
*/ |
||||
public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData) |
||||
{ |
||||
this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive()); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of DERExternal. |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param encoding The encoding to be used for the external data |
||||
* @param externalData The external data |
||||
*/ |
||||
public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData) |
||||
{ |
||||
super(directReference, indirectReference, dataValueDescriptor, encoding, externalData); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
return this.getEncoded().length; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
if (directReference != null) |
||||
{ |
||||
baos.write(directReference.getEncoded(ASN1Encoding.DER)); |
||||
} |
||||
if (indirectReference != null) |
||||
{ |
||||
baos.write(indirectReference.getEncoded(ASN1Encoding.DER)); |
||||
} |
||||
if (dataValueDescriptor != null) |
||||
{ |
||||
baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DER)); |
||||
} |
||||
DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent); |
||||
baos.write(obj.getEncoded(ASN1Encoding.DER)); |
||||
|
||||
out.writeEncoded(withTag, BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray()); |
||||
} |
||||
} |
@ -1,68 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser DER EXTERNAL tagged objects. |
||||
*/ |
||||
public class DERExternalParser |
||||
implements ASN1Encodable, InMemoryRepresentable |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @param parser the underlying parser to read the DER EXTERNAL from. |
||||
*/ |
||||
public DERExternalParser(ASN1StreamParser parser) |
||||
{ |
||||
this._parser = parser; |
||||
} |
||||
|
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the EXTERNAL object. |
||||
* |
||||
* @return a DERExternal. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
try |
||||
{ |
||||
return new DLExternal(_parser.readVector()); |
||||
} |
||||
catch (IllegalArgumentException e) |
||||
{ |
||||
throw new ASN1Exception(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return an DERExternal representing this parser and its contents. |
||||
* |
||||
* @return an DERExternal |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException ioe) |
||||
{ |
||||
throw new ASN1ParsingException("unable to get DER object", ioe); |
||||
} |
||||
catch (IllegalArgumentException ioe) |
||||
{ |
||||
throw new ASN1ParsingException("unable to get DER object", ioe); |
||||
} |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.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; |
||||
} |
||||
|
||||
return new DERSequence(v); |
||||
} |
||||
|
||||
static ASN1Set createSet(ASN1EncodableVector v) |
||||
{ |
||||
if (v.size() < 1) |
||||
{ |
||||
return EMPTY_SET; |
||||
} |
||||
|
||||
return new DERSet(v); |
||||
} |
||||
} |
@ -1,148 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* ASN.1 GENERAL-STRING data type. |
||||
* <p> |
||||
* This is an 8-bit encoded ISO 646 (ASCII) character set |
||||
* with optional escapes to other character sets. |
||||
* </p> |
||||
*/ |
||||
public class DERGeneralString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return a GeneralString 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 DERGeneralString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERGeneralString) |
||||
{ |
||||
return (DERGeneralString) obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERGeneralString)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 GeneralString 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 DERGeneralString instance. |
||||
*/ |
||||
public static DERGeneralString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERGeneralString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERGeneralString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
DERGeneralString(byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Construct a GeneralString from the passed in String. |
||||
* |
||||
* @param string the string to be contained in this object. |
||||
*/ |
||||
public DERGeneralString(String string) |
||||
{ |
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
/** |
||||
* Return a Java String representation of our contained String. |
||||
* |
||||
* @return a Java String representing our contents. |
||||
*/ |
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
/** |
||||
* Return a byte array representation of our contained String. |
||||
* |
||||
* @return a byte array representing our contents. |
||||
*/ |
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.GENERAL_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERGeneralString)) |
||||
{ |
||||
return false; |
||||
} |
||||
DERGeneralString s = (DERGeneralString)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
} |
@ -1,124 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Date; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER Generalized time object. |
||||
* <h3>11: Restrictions on BER employed by both CER and DER</h3> |
||||
* <h4>11.7 GeneralizedTime </h4> |
||||
* <p> |
||||
* <b>11.7.1</b> The encoding shall terminate with a "Z", |
||||
* as described in the ITU-T Rec. X.680 | ISO/IEC 8824-1 clause on |
||||
* GeneralizedTime. |
||||
* </p><p> |
||||
* <b>11.7.2</b> The seconds element shall always be present. |
||||
* </p> |
||||
* <p> |
||||
* <b>11.7.3</b> The fractional-seconds elements, if present, |
||||
* shall omit all trailing zeros; if the elements correspond to 0, |
||||
* they shall be wholly omitted, and the decimal point element also |
||||
* shall be omitted. |
||||
*/ |
||||
public class DERGeneralizedTime |
||||
extends ASN1GeneralizedTime |
||||
{ |
||||
public DERGeneralizedTime(byte[] time) |
||||
{ |
||||
super(time); |
||||
} |
||||
|
||||
public DERGeneralizedTime(Date time) |
||||
{ |
||||
super(time); |
||||
} |
||||
|
||||
public DERGeneralizedTime(String time) |
||||
{ |
||||
super(time); |
||||
} |
||||
|
||||
private byte[] getDERTime() |
||||
{ |
||||
if (time[time.length - 1] == 'Z') |
||||
{ |
||||
if (!hasMinutes()) |
||||
{ |
||||
byte[] derTime = new byte[time.length + 4]; |
||||
|
||||
System.arraycopy(time, 0, derTime, 0, time.length - 1); |
||||
System.arraycopy(Strings.toByteArray("0000Z"), 0, derTime, time.length - 1, 5); |
||||
|
||||
return derTime; |
||||
} |
||||
else if (!hasSeconds()) |
||||
{ |
||||
byte[] derTime = new byte[time.length + 2]; |
||||
|
||||
System.arraycopy(time, 0, derTime, 0, time.length - 1); |
||||
System.arraycopy(Strings.toByteArray("00Z"), 0, derTime, time.length - 1, 3); |
||||
|
||||
return derTime; |
||||
} |
||||
else if (hasFractionalSeconds()) |
||||
{ |
||||
int ind = time.length - 2; |
||||
while (ind > 0 && time[ind] == '0') |
||||
{ |
||||
ind--; |
||||
} |
||||
|
||||
if (time[ind] == '.') |
||||
{ |
||||
byte[] derTime = new byte[ind + 1]; |
||||
|
||||
System.arraycopy(time, 0, derTime, 0, ind); |
||||
derTime[ind] = (byte)'Z'; |
||||
|
||||
return derTime; |
||||
} |
||||
else |
||||
{ |
||||
byte[] derTime = new byte[ind + 2]; |
||||
|
||||
System.arraycopy(time, 0, derTime, 0, ind + 1); |
||||
derTime[ind + 1] = (byte)'Z'; |
||||
|
||||
return derTime; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
return time; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
return time; // TODO: is there a better way?
|
||||
} |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
int length = getDERTime().length; |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.GENERALIZED_TIME, getDERTime()); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,117 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Basic class for streaming DER encoding generators. |
||||
*/ |
||||
public abstract class DERGenerator |
||||
extends ASN1Generator |
||||
{ |
||||
private boolean _tagged = false; |
||||
private boolean _isExplicit; |
||||
private int _tagNo; |
||||
|
||||
protected DERGenerator( |
||||
OutputStream out) |
||||
{ |
||||
super(out); |
||||
} |
||||
|
||||
/** |
||||
* Create a DER encoding generator for a tagged object. |
||||
* |
||||
* @param out the output stream to encode objects to. |
||||
* @param tagNo the tag number to head the output stream with. |
||||
* @param isExplicit true if the tagging should be explicit, false otherwise. |
||||
*/ |
||||
public DERGenerator( |
||||
OutputStream out, |
||||
int tagNo, |
||||
boolean isExplicit) |
||||
{ |
||||
super(out); |
||||
|
||||
_tagged = true; |
||||
_isExplicit = isExplicit; |
||||
_tagNo = tagNo; |
||||
} |
||||
|
||||
private void writeLength( |
||||
OutputStream out, |
||||
int length) |
||||
throws IOException |
||||
{ |
||||
if (length > 127) |
||||
{ |
||||
int size = 1; |
||||
int val = length; |
||||
|
||||
while ((val >>>= 8) != 0) |
||||
{ |
||||
size++; |
||||
} |
||||
|
||||
out.write((byte)(size | 0x80)); |
||||
|
||||
for (int i = (size - 1) * 8; i >= 0; i -= 8) |
||||
{ |
||||
out.write((byte)(length >> i)); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
out.write((byte)length); |
||||
} |
||||
} |
||||
|
||||
void writeDEREncoded( |
||||
OutputStream out, |
||||
int tag, |
||||
byte[] bytes) |
||||
throws IOException |
||||
{ |
||||
out.write(tag); |
||||
writeLength(out, bytes.length); |
||||
out.write(bytes); |
||||
} |
||||
|
||||
void writeDEREncoded( |
||||
int tag, |
||||
byte[] bytes) |
||||
throws IOException |
||||
{ |
||||
if (_tagged) |
||||
{ |
||||
int tagNum = _tagNo | BERTags.TAGGED; |
||||
|
||||
if (_isExplicit) |
||||
{ |
||||
int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED; |
||||
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
||||
|
||||
writeDEREncoded(bOut, tag, bytes); |
||||
|
||||
writeDEREncoded(_out, newTag, bOut.toByteArray()); |
||||
} |
||||
else |
||||
{ |
||||
if ((tag & BERTags.CONSTRUCTED) != 0) |
||||
{ |
||||
writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes); |
||||
} |
||||
else |
||||
{ |
||||
writeDEREncoded(_out, tagNum, bytes); |
||||
} |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
writeDEREncoded(_out, tag, bytes); |
||||
} |
||||
} |
||||
} |
@ -1,122 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
public class DERGraphicString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* return a Graphic String from the passed in object |
||||
* |
||||
* @param obj a DERGraphicString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERGraphicString instance, or null. |
||||
*/ |
||||
public static DERGraphicString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERGraphicString) |
||||
{ |
||||
return (DERGraphicString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERGraphicString)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 Graphic 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 DERGraphicString instance, or null. |
||||
*/ |
||||
public static DERGraphicString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERGraphicString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERGraphicString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* basic constructor - with bytes. |
||||
* @param string the byte encoding of the characters making up the string. |
||||
*/ |
||||
public DERGraphicString( |
||||
byte[] string) |
||||
{ |
||||
this.string = Arrays.clone(string); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.GRAPHIC_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERGraphicString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERGraphicString s = (DERGraphicString)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
} |
@ -1,190 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER IA5String object - this is a ISO 646 (ASCII) string encoding code points 0 to 127. |
||||
* <p> |
||||
* Explicit character set escape sequences are not allowed. |
||||
* </p> |
||||
*/ |
||||
public class DERIA5String |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return an IA5 string from the passed in object |
||||
* |
||||
* @param obj a DERIA5String or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERIA5String instance, or null. |
||||
*/ |
||||
public static DERIA5String getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERIA5String) |
||||
{ |
||||
return (DERIA5String)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERIA5String)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 IA5 String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERIA5String instance, or null. |
||||
*/ |
||||
public static DERIA5String getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERIA5String) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERIA5String(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - with bytes. |
||||
* @param string the byte encoding of the characters making up the string. |
||||
*/ |
||||
DERIA5String( |
||||
byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - without validation. |
||||
* @param string the base string to use.. |
||||
*/ |
||||
public DERIA5String( |
||||
String string) |
||||
{ |
||||
this(string, false); |
||||
} |
||||
|
||||
/** |
||||
* Constructor with optional validation. |
||||
* |
||||
* @param string the base string to wrap. |
||||
* @param validate whether or not to check the string. |
||||
* @throws IllegalArgumentException if validate is true and the string |
||||
* contains characters that should not be in an IA5String. |
||||
*/ |
||||
public DERIA5String( |
||||
String string, |
||||
boolean validate) |
||||
{ |
||||
if (string == null) |
||||
{ |
||||
throw new NullPointerException("'string' cannot be null"); |
||||
} |
||||
if (validate && !isIA5String(string)) |
||||
{ |
||||
throw new IllegalArgumentException("'string' contains illegal characters"); |
||||
} |
||||
|
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.IA5_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERIA5String)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERIA5String s = (DERIA5String)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
/** |
||||
* return true if the passed in String can be represented without |
||||
* loss as an IA5String, false otherwise. |
||||
* |
||||
* @param str the string to check. |
||||
* @return true if character set in IA5String set, false otherwise. |
||||
*/ |
||||
public static boolean isIA5String( |
||||
String str) |
||||
{ |
||||
for (int i = str.length() - 1; i >= 0; i--) |
||||
{ |
||||
char ch = str.charAt(i); |
||||
|
||||
if (ch > 0x007f) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
@ -1,35 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* An ASN.1 DER NULL object. |
||||
* <p> |
||||
* Preferably use the constant: DERNull.INSTANCE. |
||||
*/ |
||||
public class DERNull |
||||
extends ASN1Null |
||||
{ |
||||
public static final DERNull INSTANCE = new DERNull(); |
||||
|
||||
private static final byte[] zeroBytes = new byte[0]; |
||||
|
||||
private DERNull() |
||||
{ |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 2; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.NULL, zeroBytes); |
||||
} |
||||
} |
@ -1,194 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }. |
||||
* ASN.1 NUMERIC-STRING object. |
||||
* <p> |
||||
* This is an ASCII string of characters {0,1,2,3,4,5,6,7,8,9} + space. |
||||
* <p> |
||||
* See X.680 section 37.2. |
||||
* <p> |
||||
* Explicit character set escape sequences are not allowed. |
||||
*/ |
||||
public class DERNumericString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return a Numeric string from the passed in object |
||||
* |
||||
* @param obj a DERNumericString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERNumericString instance, or null |
||||
*/ |
||||
public static DERNumericString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERNumericString) |
||||
{ |
||||
return (DERNumericString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERNumericString)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 Numeric String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERNumericString instance, or null. |
||||
*/ |
||||
public static DERNumericString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERNumericString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERNumericString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - with bytes. |
||||
*/ |
||||
DERNumericString( |
||||
byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - without validation.. |
||||
*/ |
||||
public DERNumericString( |
||||
String string) |
||||
{ |
||||
this(string, false); |
||||
} |
||||
|
||||
/** |
||||
* Constructor with optional validation. |
||||
* |
||||
* @param string the base string to wrap. |
||||
* @param validate whether or not to check the string. |
||||
* @throws IllegalArgumentException if validate is true and the string |
||||
* contains characters that should not be in a NumericString. |
||||
*/ |
||||
public DERNumericString( |
||||
String string, |
||||
boolean validate) |
||||
{ |
||||
if (validate && !isNumericString(string)) |
||||
{ |
||||
throw new IllegalArgumentException("string contains illegal characters"); |
||||
} |
||||
|
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.NUMERIC_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERNumericString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERNumericString s = (DERNumericString)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
/** |
||||
* Return true if the string can be represented as a NumericString ('0'..'9', ' ') |
||||
* |
||||
* @param str string to validate. |
||||
* @return true if numeric, fale otherwise. |
||||
*/ |
||||
public static boolean isNumericString( |
||||
String str) |
||||
{ |
||||
for (int i = str.length() - 1; i >= 0; i--) |
||||
{ |
||||
char ch = str.charAt(i); |
||||
|
||||
if (ch > 0x007f) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
if (('0' <= ch && ch <= '9') || ch == ' ') |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
@ -1,63 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Carrier class for a DER encoding OCTET STRING |
||||
*/ |
||||
public class DEROctetString |
||||
extends ASN1OctetString |
||||
{ |
||||
/** |
||||
* Base constructor. |
||||
* |
||||
* @param string the octets making up the octet string. |
||||
*/ |
||||
public DEROctetString( |
||||
byte[] string) |
||||
{ |
||||
super(string); |
||||
} |
||||
|
||||
/** |
||||
* Constructor from the encoding of an ASN.1 object. |
||||
* |
||||
* @param obj the object to be encoded. |
||||
*/ |
||||
public DEROctetString( |
||||
ASN1Encodable obj) |
||||
throws IOException |
||||
{ |
||||
super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER)); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.OCTET_STRING, string); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
static void encode(ASN1OutputStream derOut, boolean withTag, byte[] buf, int off, int len) throws IOException |
||||
{ |
||||
derOut.writeEncoded(withTag, BERTags.OCTET_STRING, buf, off, len); |
||||
} |
||||
} |
@ -1,58 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
/** |
||||
* Parser for DER encoded OCTET STRINGS |
||||
*/ |
||||
public class DEROctetStringParser |
||||
implements ASN1OctetStringParser |
||||
{ |
||||
private DefiniteLengthInputStream stream; |
||||
|
||||
DEROctetStringParser( |
||||
DefiniteLengthInputStream stream) |
||||
{ |
||||
this.stream = stream; |
||||
} |
||||
|
||||
/** |
||||
* Return an InputStream representing the contents of the OCTET STRING. |
||||
* |
||||
* @return an InputStream with its source as the OCTET STRING content. |
||||
*/ |
||||
public InputStream getOctetStream() |
||||
{ |
||||
return stream; |
||||
} |
||||
|
||||
/** |
||||
* Return an in-memory, encodable, representation of the OCTET STRING. |
||||
* |
||||
* @return a DEROctetString. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new DEROctetString(stream.toByteArray()); |
||||
} |
||||
|
||||
/** |
||||
* Return an DEROctetString representing this parser and its contents. |
||||
* |
||||
* @return an DEROctetString |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -1,31 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Stream that outputs encoding based on distinguished encoding rules. |
||||
*/ |
||||
class DEROutputStream |
||||
extends ASN1OutputStream |
||||
{ |
||||
DEROutputStream(OutputStream os) |
||||
{ |
||||
super(os); |
||||
} |
||||
|
||||
void writePrimitive(ASN1Primitive primitive, boolean withTag) throws IOException |
||||
{ |
||||
primitive.toDERObject().encode(this, withTag); |
||||
} |
||||
|
||||
DEROutputStream getDERSubStream() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1OutputStream getDLSubStream() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,237 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER PrintableString object. |
||||
* <p> |
||||
* X.680 section 37.4 defines PrintableString character codes as ASCII subset of following characters: |
||||
* </p> |
||||
* <ul> |
||||
* <li>Latin capital letters: 'A' .. 'Z'</li> |
||||
* <li>Latin small letters: 'a' .. 'z'</li> |
||||
* <li>Digits: '0'..'9'</li> |
||||
* <li>Space</li> |
||||
* <li>Apostrophe: '\''</li> |
||||
* <li>Left parenthesis: '('</li> |
||||
* <li>Right parenthesis: ')'</li> |
||||
* <li>Plus sign: '+'</li> |
||||
* <li>Comma: ','</li> |
||||
* <li>Hyphen-minus: '-'</li> |
||||
* <li>Full stop: '.'</li> |
||||
* <li>Solidus: '/'</li> |
||||
* <li>Colon: ':'</li> |
||||
* <li>Equals sign: '='</li> |
||||
* <li>Question mark: '?'</li> |
||||
* </ul> |
||||
* <p> |
||||
* Explicit character set escape sequences are not allowed. |
||||
* </p> |
||||
*/ |
||||
public class DERPrintableString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return a printable string from the passed in object. |
||||
* |
||||
* @param obj a DERPrintableString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERPrintableString instance, or null. |
||||
*/ |
||||
public static DERPrintableString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERPrintableString) |
||||
{ |
||||
return (DERPrintableString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERPrintableString)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 Printable String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERPrintableString instance, or null. |
||||
*/ |
||||
public static DERPrintableString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERPrintableString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERPrintableString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - byte encoded string. |
||||
*/ |
||||
DERPrintableString( |
||||
byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - this does not validate the string |
||||
*/ |
||||
public DERPrintableString( |
||||
String string) |
||||
{ |
||||
this(string, false); |
||||
} |
||||
|
||||
/** |
||||
* Constructor with optional validation. |
||||
* |
||||
* @param string the base string to wrap. |
||||
* @param validate whether or not to check the string. |
||||
* @throws IllegalArgumentException if validate is true and the string |
||||
* contains characters that should not be in a PrintableString. |
||||
*/ |
||||
public DERPrintableString( |
||||
String string, |
||||
boolean validate) |
||||
{ |
||||
if (validate && !isPrintableString(string)) |
||||
{ |
||||
throw new IllegalArgumentException("string contains illegal characters"); |
||||
} |
||||
|
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.PRINTABLE_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERPrintableString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERPrintableString s = (DERPrintableString)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
/** |
||||
* return true if the passed in String can be represented without |
||||
* loss as a PrintableString, false otherwise. |
||||
* |
||||
* @return true if in printable set, false otherwise. |
||||
*/ |
||||
public static boolean isPrintableString( |
||||
String str) |
||||
{ |
||||
for (int i = str.length() - 1; i >= 0; i--) |
||||
{ |
||||
char ch = str.charAt(i); |
||||
|
||||
if (ch > 0x007f) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
if ('a' <= ch && ch <= 'z') |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
if ('A' <= ch && ch <= 'Z') |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
if ('0' <= ch && ch <= '9') |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
switch (ch) |
||||
{ |
||||
case ' ': |
||||
case '\'': |
||||
case '(': |
||||
case ')': |
||||
case '+': |
||||
case '-': |
||||
case '.': |
||||
case ':': |
||||
case '=': |
||||
case '?': |
||||
case '/': |
||||
case ',': |
||||
continue; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
@ -1,145 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Definite length SEQUENCE, encoding tells explicit number of bytes |
||||
* that the content of this sequence occupies. |
||||
* <p> |
||||
* For X.690 syntax rules, see {@link ASN1Sequence}. |
||||
*/ |
||||
public class DERSequence |
||||
extends ASN1Sequence |
||||
{ |
||||
public static DERSequence convert(ASN1Sequence seq) |
||||
{ |
||||
return (DERSequence)seq.toDERObject(); |
||||
} |
||||
|
||||
private int bodyLength = -1; |
||||
|
||||
/** |
||||
* Create an empty sequence |
||||
*/ |
||||
public DERSequence() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing one object |
||||
* @param element the object to go in the sequence. |
||||
*/ |
||||
public DERSequence(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing a vector of objects. |
||||
* @param elementVector the vector of objects to make up the sequence. |
||||
*/ |
||||
public DERSequence(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector); |
||||
} |
||||
|
||||
/** |
||||
* Create a sequence containing an array of objects. |
||||
* @param elements the array of objects to make up the sequence. |
||||
*/ |
||||
public DERSequence(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements); |
||||
} |
||||
|
||||
DERSequence(ASN1Encodable[] elements, boolean clone) |
||||
{ |
||||
super(elements, clone); |
||||
} |
||||
|
||||
private int getBodyLength() throws IOException |
||||
{ |
||||
if (bodyLength < 0) |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
totalLength += derObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
} |
||||
|
||||
return bodyLength; |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int length = getBodyLength(); |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
/* |
||||
* A note on the implementation: |
||||
* <p> |
||||
* As DER requires the constructed, definite-length model to |
||||
* be used for structured types, this varies slightly from the |
||||
* ASN.1 descriptions given. Rather than just outputting SEQUENCE, |
||||
* we also have to specify CONSTRUCTED, and the objects length. |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED); |
||||
} |
||||
|
||||
DEROutputStream derOut = out.getDERSubStream(); |
||||
|
||||
int count = elements.length; |
||||
if (bodyLength >= 0 || count > 16) |
||||
{ |
||||
out.writeLength(getBodyLength()); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
derObject.encode(derOut, true); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
int totalLength = 0; |
||||
|
||||
ASN1Primitive[] derObjects = new ASN1Primitive[count]; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
derObjects[i] = derObject; |
||||
totalLength += derObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
out.writeLength(totalLength); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
derObjects[i].encode(derOut, true); |
||||
} |
||||
} |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,79 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* A stream generator for DER SEQUENCEs |
||||
*/ |
||||
public class DERSequenceGenerator |
||||
extends DERGenerator |
||||
{ |
||||
private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream(); |
||||
|
||||
/** |
||||
* Use the passed in stream as the target for the generator. |
||||
* |
||||
* @param out target stream |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public DERSequenceGenerator( |
||||
OutputStream out) |
||||
throws IOException |
||||
{ |
||||
super(out); |
||||
} |
||||
|
||||
/** |
||||
* Use the passed in stream as the target for the generator, writing out the header tag |
||||
* for a tagged constructed SEQUENCE (possibly implicit). |
||||
* |
||||
* @param out target stream |
||||
* @param tagNo the tag number to introduce |
||||
* @param isExplicit true if this is an explicitly tagged object, false otherwise. |
||||
* @throws IOException if the target stream cannot be written to. |
||||
*/ |
||||
public DERSequenceGenerator( |
||||
OutputStream out, |
||||
int tagNo, |
||||
boolean isExplicit) |
||||
throws IOException |
||||
{ |
||||
super(out, tagNo, isExplicit); |
||||
} |
||||
|
||||
/** |
||||
* Add an object to the SEQUENCE being generated. |
||||
* |
||||
* @param object an ASN.1 encodable object to add. |
||||
* @throws IOException if the target stream cannot be written to or the object cannot be encoded. |
||||
*/ |
||||
public void addObject( |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
object.toASN1Primitive().encodeTo(_bOut, ASN1Encoding.DER); |
||||
} |
||||
|
||||
/** |
||||
* Return the target stream for the SEQUENCE. |
||||
* |
||||
* @return the OutputStream the SEQUENCE is being written to. |
||||
*/ |
||||
public OutputStream getRawOutputStream() |
||||
{ |
||||
return _bOut; |
||||
} |
||||
|
||||
/** |
||||
* Close of the generator, writing out the SEQUENCE. |
||||
* |
||||
* @throws IOException if the target stream cannot be written. |
||||
*/ |
||||
public void close() |
||||
throws IOException |
||||
{ |
||||
writeDEREncoded(BERTags.CONSTRUCTED | BERTags.SEQUENCE, _bOut.toByteArray()); |
||||
} |
||||
} |
@ -1,158 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A DER encoded SET object |
||||
* <p> |
||||
* For X.690 syntax rules, see {@link ASN1Set}. |
||||
* </p><p> |
||||
* For short: Constructing this form does sort the supplied elements, |
||||
* and the sorting happens also before serialization (if necesssary). |
||||
* This is different from the way {@link BERSet},{@link DLSet} does things. |
||||
* </p> |
||||
*/ |
||||
public class DERSet |
||||
extends ASN1Set |
||||
{ |
||||
public static DERSet convert(ASN1Set set) |
||||
{ |
||||
return (DERSet)set.toDERObject(); |
||||
} |
||||
|
||||
private int bodyLength = -1; |
||||
|
||||
/** |
||||
* create an empty set |
||||
*/ |
||||
public DERSet() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* create a set containing one object |
||||
* @param element the object to go in the set |
||||
*/ |
||||
public DERSet(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* create a set containing a vector of objects. |
||||
* @param elementVector the vector of objects to make up the set. |
||||
*/ |
||||
public DERSet(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector, true); |
||||
} |
||||
|
||||
/** |
||||
* create a set containing an array of objects. |
||||
* @param elements the array of objects to make up the set. |
||||
*/ |
||||
public DERSet(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements, true); |
||||
} |
||||
|
||||
DERSet(boolean isSorted, ASN1Encodable[] elements) |
||||
{ |
||||
super(checkSorted(isSorted), elements); |
||||
} |
||||
|
||||
private int getBodyLength() throws IOException |
||||
{ |
||||
if (bodyLength < 0) |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
totalLength += derObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
} |
||||
|
||||
return bodyLength; |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int length = getBodyLength(); |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
/* |
||||
* A note on the implementation: |
||||
* <p> |
||||
* As DER requires the constructed, definite-length model to |
||||
* be used for structured types, this varies slightly from the |
||||
* ASN.1 descriptions given. Rather than just outputting SET, |
||||
* we also have to specify CONSTRUCTED, and the objects length. |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
out.write(BERTags.SET | BERTags.CONSTRUCTED); |
||||
} |
||||
|
||||
DEROutputStream derOut = out.getDERSubStream(); |
||||
|
||||
int count = elements.length; |
||||
if (bodyLength >= 0 || count > 16) |
||||
{ |
||||
out.writeLength(getBodyLength()); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
derObject.encode(derOut, true); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
int totalLength = 0; |
||||
|
||||
ASN1Primitive[] derObjects = new ASN1Primitive[count]; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject(); |
||||
derObjects[i] = derObject; |
||||
totalLength += derObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
out.writeLength(totalLength); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
derObjects[i].encode(derOut, true); |
||||
} |
||||
} |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return isSorted ? this : super.toDERObject(); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
private static boolean checkSorted(boolean isSorted) |
||||
{ |
||||
if (!isSorted) |
||||
{ |
||||
throw new IllegalStateException("DERSet elements should always be in sorted order"); |
||||
} |
||||
return isSorted; |
||||
} |
||||
} |
@ -1,149 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER T61String (also the teletex string), try not to use this if you don't need to. The standard support the encoding for |
||||
* this has been withdrawn. |
||||
*/ |
||||
public class DERT61String |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private byte[] string; |
||||
|
||||
/** |
||||
* Return a T61 string from the passed in object. |
||||
* |
||||
* @param obj a DERT61String or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERT61String instance, or null |
||||
*/ |
||||
public static DERT61String getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERT61String) |
||||
{ |
||||
return (DERT61String)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERT61String)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 T61 String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERT61String instance, or null |
||||
*/ |
||||
public static DERT61String getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERT61String) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERT61String(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - string encoded as a sequence of bytes. |
||||
* |
||||
* @param string the byte encoding of the string to be wrapped. |
||||
*/ |
||||
public DERT61String( |
||||
byte[] string) |
||||
{ |
||||
this.string = Arrays.clone(string); |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - with string 8 bit assumed. |
||||
* |
||||
* @param string the string to be wrapped. |
||||
*/ |
||||
public DERT61String( |
||||
String string) |
||||
{ |
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
/** |
||||
* Decode the encoded string and return it, 8 bit encoding assumed. |
||||
* @return the decoded String |
||||
*/ |
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.T61_STRING, string); |
||||
} |
||||
|
||||
/** |
||||
* Return the encoded string as a byte array. |
||||
* @return the actual bytes making up the encoded body of the T61 string. |
||||
*/ |
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERT61String)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return Arrays.areEqual(string, ((DERT61String)o).string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
} |
@ -1,84 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* DER TaggedObject - in ASN.1 notation this is any object preceded by |
||||
* a [n] where n is some number - these are assumed to follow the construction |
||||
* rules (as with sequences). |
||||
*/ |
||||
public class DERTaggedObject |
||||
extends ASN1TaggedObject |
||||
{ |
||||
/** |
||||
* @param explicit true if an explicitly tagged object. |
||||
* @param tagNo the tag number for this object. |
||||
* @param obj the tagged object. |
||||
*/ |
||||
public DERTaggedObject( |
||||
boolean explicit, |
||||
int tagNo, |
||||
ASN1Encodable obj) |
||||
{ |
||||
super(explicit, tagNo, obj); |
||||
} |
||||
|
||||
public DERTaggedObject(int tagNo, ASN1Encodable encodable) |
||||
{ |
||||
super(true, tagNo, encodable); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return explicit || obj.toASN1Primitive().toDERObject().isConstructed(); |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); |
||||
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; |
||||
} |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); |
||||
|
||||
int flags = BERTags.TAGGED; |
||||
if (explicit || primitive.isConstructed()) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeTag(withTag, flags, tagNo); |
||||
|
||||
if (explicit) |
||||
{ |
||||
out.writeLength(primitive.encodedLength()); |
||||
} |
||||
|
||||
primitive.encode(out.getDERSubStream(), explicit); |
||||
} |
||||
|
||||
ASN1Primitive toDERObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* DER UTC time object. |
||||
*/ |
||||
public class DERUTCTime |
||||
extends ASN1UTCTime |
||||
{ |
||||
DERUTCTime(byte[] bytes) |
||||
{ |
||||
super(bytes); |
||||
} |
||||
|
||||
public DERUTCTime(Date time) |
||||
{ |
||||
super(time); |
||||
} |
||||
|
||||
public DERUTCTime(String time) |
||||
{ |
||||
super(time); |
||||
} |
||||
|
||||
// TODO: create proper DER encoding.
|
||||
} |
@ -1,136 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER UTF8String object. |
||||
*/ |
||||
public class DERUTF8String |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return an UTF8 string from the passed in object. |
||||
* |
||||
* @param obj a DERUTF8String or an object that can be converted into one. |
||||
* @exception IllegalArgumentException |
||||
* if the object cannot be converted. |
||||
* @return a DERUTF8String instance, or null |
||||
*/ |
||||
public static DERUTF8String getInstance(Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERUTF8String) |
||||
{ |
||||
return (DERUTF8String)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERUTF8String)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 UTF8 String from a tagged object. |
||||
* |
||||
* @param obj |
||||
* the tagged object holding the object we want |
||||
* @param explicit |
||||
* true if the object is meant to be explicitly tagged false |
||||
* otherwise. |
||||
* @exception IllegalArgumentException |
||||
* if the tagged object cannot be converted. |
||||
* @return a DERUTF8String instance, or null |
||||
*/ |
||||
public static DERUTF8String getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERUTF8String) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERUTF8String(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Basic constructor - byte encoded string. |
||||
*/ |
||||
DERUTF8String(byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor |
||||
* |
||||
* @param string the string to be carried in the UTF8String object, |
||||
*/ |
||||
public DERUTF8String(String string) |
||||
{ |
||||
this.string = Strings.toUTF8ByteArray(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromUTF8ByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals(ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERUTF8String)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERUTF8String s = (DERUTF8String)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.UTF8_STRING, string); |
||||
} |
||||
} |
@ -1,148 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
|
||||
/** |
||||
* DER UniversalString object - encodes UNICODE (ISO 10646) characters using 32-bit format. In Java we |
||||
* have no way of representing this directly so we rely on byte arrays to carry these. |
||||
*/ |
||||
public class DERUniversalString |
||||
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' }; |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return a Universal String from the passed in object. |
||||
* |
||||
* @param obj a DERUniversalString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERUniversalString instance, or null |
||||
*/ |
||||
public static DERUniversalString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERUniversalString) |
||||
{ |
||||
return (DERUniversalString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERUniversalString)fromByteArray((byte[])obj); |
||||
} |
||||
catch (Exception e) |
||||
{ |
||||
throw new IllegalArgumentException("encoding error getInstance: " + e.toString()); |
||||
} |
||||
} |
||||
|
||||
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); |
||||
} |
||||
|
||||
/** |
||||
* Return a Universal String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERUniversalString instance, or null |
||||
*/ |
||||
public static DERUniversalString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERUniversalString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERUniversalString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor - byte encoded string. |
||||
* |
||||
* @param string the byte encoding of the string to be carried in the UniversalString object, |
||||
*/ |
||||
public DERUniversalString( |
||||
byte[] string) |
||||
{ |
||||
this.string = Arrays.clone(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
StringBuffer buf = new StringBuffer("#"); |
||||
|
||||
byte[] string; |
||||
try |
||||
{ |
||||
string = getEncoded(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("internal error encoding UniversalString"); |
||||
} |
||||
|
||||
for (int i = 0; i != string.length; i++) |
||||
{ |
||||
buf.append(table[(string[i] >>> 4) & 0xf]); |
||||
buf.append(table[string[i] & 0xf]); |
||||
} |
||||
|
||||
return buf.toString(); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.UNIVERSAL_STRING, string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERUniversalString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return Arrays.areEqual(string, ((DERUniversalString)o).string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
} |
@ -1,122 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
public class DERVideotexString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* return a Videotex String from the passed in object |
||||
* |
||||
* @param obj a DERVideotexString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERVideotexString instance, or null. |
||||
*/ |
||||
public static DERVideotexString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERVideotexString) |
||||
{ |
||||
return (DERVideotexString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERVideotexString)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 Videotex 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 DERVideotexString instance, or null. |
||||
*/ |
||||
public static DERVideotexString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERVideotexString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERVideotexString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* basic constructor - with bytes. |
||||
* @param string the byte encoding of the characters making up the string. |
||||
*/ |
||||
public DERVideotexString( |
||||
byte[] string) |
||||
{ |
||||
this.string = Arrays.clone(string); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.VIDEOTEX_STRING, string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERVideotexString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
DERVideotexString s = (DERVideotexString)o; |
||||
|
||||
return Arrays.areEqual(string, s.string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
} |
@ -1,141 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.Arrays; |
||||
import com.fr.third.org.bouncycastle.util.Strings; |
||||
|
||||
/** |
||||
* DER VisibleString object encoding ISO 646 (ASCII) character code points 32 to 126. |
||||
* <p> |
||||
* Explicit character set escape sequences are not allowed. |
||||
* </p> |
||||
*/ |
||||
public class DERVisibleString |
||||
extends ASN1Primitive |
||||
implements ASN1String |
||||
{ |
||||
private final byte[] string; |
||||
|
||||
/** |
||||
* Return a Visible String from the passed in object. |
||||
* |
||||
* @param obj a DERVisibleString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return a DERVisibleString instance, or null |
||||
*/ |
||||
public static DERVisibleString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DERVisibleString) |
||||
{ |
||||
return (DERVisibleString)obj; |
||||
} |
||||
|
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (DERVisibleString)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 Visible String from a tagged object. |
||||
* |
||||
* @param obj the tagged object holding the object we want |
||||
* @param explicit true if the object is meant to be explicitly |
||||
* tagged false otherwise. |
||||
* @exception IllegalArgumentException if the tagged object cannot |
||||
* be converted. |
||||
* @return a DERVisibleString instance, or null |
||||
*/ |
||||
public static DERVisibleString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DERVisibleString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return new DERVisibleString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Basic constructor - byte encoded string. |
||||
*/ |
||||
DERVisibleString( |
||||
byte[] string) |
||||
{ |
||||
this.string = string; |
||||
} |
||||
|
||||
/** |
||||
* Basic constructor |
||||
* |
||||
* @param string the string to be carried in the VisibleString object, |
||||
*/ |
||||
public DERVisibleString( |
||||
String string) |
||||
{ |
||||
this.string = Strings.toByteArray(string); |
||||
} |
||||
|
||||
public String getString() |
||||
{ |
||||
return Strings.fromByteArray(string); |
||||
} |
||||
|
||||
public String toString() |
||||
{ |
||||
return getString(); |
||||
} |
||||
|
||||
public byte[] getOctets() |
||||
{ |
||||
return Arrays.clone(string); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(string.length) + string.length; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.VISIBLE_STRING, this.string); |
||||
} |
||||
|
||||
boolean asn1Equals( |
||||
ASN1Primitive o) |
||||
{ |
||||
if (!(o instanceof DERVisibleString)) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
return Arrays.areEqual(string, ((DERVisibleString)o).string); |
||||
} |
||||
|
||||
public int hashCode() |
||||
{ |
||||
return Arrays.hashCode(string); |
||||
} |
||||
} |
@ -1,124 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A DER encoding version of an application specific object. |
||||
*/ |
||||
public class DLApplicationSpecific |
||||
extends ASN1ApplicationSpecific |
||||
{ |
||||
DLApplicationSpecific( |
||||
boolean isConstructed, |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
super(isConstructed, tag, octets); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object from the passed in data. This will assume |
||||
* the data does not represent a constructed object. |
||||
* |
||||
* @param tag the tag number for this object. |
||||
* @param octets the encoding of the object's body. |
||||
*/ |
||||
public DLApplicationSpecific( |
||||
int tag, |
||||
byte[] octets) |
||||
{ |
||||
this(false, tag, octets); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with a tagging of explicit/constructed. |
||||
* |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public DLApplicationSpecific( |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
this(true, tag, object); |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object with the tagging style given by the value of constructed. |
||||
* |
||||
* @param constructed true if the object is constructed. |
||||
* @param tag the tag number for this object. |
||||
* @param object the object to be contained. |
||||
*/ |
||||
public DLApplicationSpecific( |
||||
boolean constructed, |
||||
int tag, |
||||
ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object)); |
||||
} |
||||
|
||||
private static byte[] getEncoding(boolean explicit, ASN1Encodable object) |
||||
throws IOException |
||||
{ |
||||
byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.DL); |
||||
|
||||
if (explicit) |
||||
{ |
||||
return data; |
||||
} |
||||
else |
||||
{ |
||||
int lenBytes = getLengthOfHeader(data); |
||||
byte[] tmp = new byte[data.length - lenBytes]; |
||||
System.arraycopy(data, lenBytes, tmp, 0, tmp.length); |
||||
return tmp; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create an application specific object which is marked as constructed |
||||
* |
||||
* @param tagNo the tag number for this object. |
||||
* @param vec the objects making up the application specific object. |
||||
*/ |
||||
public DLApplicationSpecific(int tagNo, ASN1EncodableVector vec) |
||||
{ |
||||
super(true, tagNo, getEncodedVector(vec)); |
||||
} |
||||
|
||||
private static byte[] getEncodedVector(ASN1EncodableVector vec) |
||||
{ |
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
||||
|
||||
for (int i = 0; i != vec.size(); i++) |
||||
{ |
||||
try |
||||
{ |
||||
bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DL)); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException("malformed object: " + e, e); |
||||
} |
||||
} |
||||
return bOut.toByteArray(); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
int flags = BERTags.APPLICATION; |
||||
if (isConstructed) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeEncoded(withTag, flags, tag, octets); |
||||
} |
||||
} |
@ -1,142 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* A Definite length BIT STRING |
||||
*/ |
||||
public class DLBitString |
||||
extends ASN1BitString |
||||
{ |
||||
/** |
||||
* return a Bit String that can be definite-length encoded from the passed in object. |
||||
* |
||||
* @param obj a DL or DER BitString or an object that can be converted into one. |
||||
* @exception IllegalArgumentException if the object cannot be converted. |
||||
* @return an ASN1BitString instance, or null. |
||||
*/ |
||||
public static ASN1BitString getInstance( |
||||
Object obj) |
||||
{ |
||||
if (obj == null || obj instanceof DLBitString) |
||||
{ |
||||
return (DLBitString)obj; |
||||
} |
||||
if (obj instanceof DERBitString) |
||||
{ |
||||
return (DERBitString)obj; |
||||
} |
||||
if (obj instanceof byte[]) |
||||
{ |
||||
try |
||||
{ |
||||
return (ASN1BitString)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 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 an ASN1BitString instance, or null. |
||||
*/ |
||||
public static ASN1BitString getInstance( |
||||
ASN1TaggedObject obj, |
||||
boolean explicit) |
||||
{ |
||||
ASN1Primitive o = obj.getObject(); |
||||
|
||||
if (explicit || o instanceof DLBitString) |
||||
{ |
||||
return getInstance(o); |
||||
} |
||||
else |
||||
{ |
||||
return fromOctetString(ASN1OctetString.getInstance(o).getOctets()); |
||||
} |
||||
} |
||||
|
||||
protected DLBitString(byte data, int padBits) |
||||
{ |
||||
super(data, padBits); |
||||
} |
||||
|
||||
/** |
||||
* @param data the octets making up the bit string. |
||||
* @param padBits the number of extra bits at the end of the string. |
||||
*/ |
||||
public DLBitString( |
||||
byte[] data, |
||||
int padBits) |
||||
{ |
||||
super(data, padBits); |
||||
} |
||||
|
||||
public DLBitString( |
||||
byte[] data) |
||||
{ |
||||
this(data, 0); |
||||
} |
||||
|
||||
public DLBitString( |
||||
int value) |
||||
{ |
||||
super(getBytes(value), getPadBits(value)); |
||||
} |
||||
|
||||
public DLBitString( |
||||
ASN1Encodable obj) |
||||
throws IOException |
||||
{ |
||||
super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
int encodedLength() |
||||
{ |
||||
return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1; |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
out.writeEncoded(withTag, BERTags.BIT_STRING, (byte)padBits, data); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
static DLBitString 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 DLBitString(data, padBits); |
||||
} |
||||
} |
@ -1,90 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Class representing the Definite-Length-type External |
||||
*/ |
||||
public class DLExternal |
||||
extends ASN1External |
||||
{ |
||||
/** |
||||
* Construct a Definite-Length EXTERNAL object, the input encoding vector must have exactly two elements on it. |
||||
* <p> |
||||
* Acceptable input formats are: |
||||
* <ul> |
||||
* <li> {@link ASN1ObjectIdentifier} + data {@link DERTaggedObject} (direct reference form)</li> |
||||
* <li> {@link ASN1Integer} + data {@link DERTaggedObject} (indirect reference form)</li> |
||||
* <li> Anything but {@link DERTaggedObject} + data {@link DERTaggedObject} (data value form)</li> |
||||
* </ul> |
||||
* |
||||
* @throws IllegalArgumentException if input size is wrong, or |
||||
*/ |
||||
public DLExternal(ASN1EncodableVector vector) |
||||
{ |
||||
super(vector); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of DERExternal |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param externalData The external data in its encoded form. |
||||
*/ |
||||
public DLExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData) |
||||
{ |
||||
this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive()); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new instance of Definite-Length External. |
||||
* See X.690 for more informations about the meaning of these parameters |
||||
* @param directReference The direct reference or <code>null</code> if not set. |
||||
* @param indirectReference The indirect reference or <code>null</code> if not set. |
||||
* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set. |
||||
* @param encoding The encoding to be used for the external data |
||||
* @param externalData The external data |
||||
*/ |
||||
public DLExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData) |
||||
{ |
||||
super(directReference, indirectReference, dataValueDescriptor, encoding, externalData); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
return this.getEncoded().length; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see com.fr.third.org.bouncycastle.asn1.ASN1Primitive#encode(com.fr.third.org.bouncycastle.asn1.DEROutputStream) |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
if (directReference != null) |
||||
{ |
||||
baos.write(directReference.getEncoded(ASN1Encoding.DL)); |
||||
} |
||||
if (indirectReference != null) |
||||
{ |
||||
baos.write(indirectReference.getEncoded(ASN1Encoding.DL)); |
||||
} |
||||
if (dataValueDescriptor != null) |
||||
{ |
||||
baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DL)); |
||||
} |
||||
ASN1TaggedObject obj = new DLTaggedObject(true, encoding, externalContent); |
||||
baos.write(obj.getEncoded(ASN1Encoding.DL)); |
||||
|
||||
out.writeEncoded(withTag, BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray()); |
||||
} |
||||
} |
@ -1,27 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
class DLFactory |
||||
{ |
||||
static final ASN1Sequence EMPTY_SEQUENCE = new DLSequence(); |
||||
static final ASN1Set EMPTY_SET = new DLSet(); |
||||
|
||||
static ASN1Sequence createSequence(ASN1EncodableVector v) |
||||
{ |
||||
if (v.size() < 1) |
||||
{ |
||||
return EMPTY_SEQUENCE; |
||||
} |
||||
|
||||
return new DLSequence(v); |
||||
} |
||||
|
||||
static ASN1Set createSet(ASN1EncodableVector v) |
||||
{ |
||||
if (v.size() < 1) |
||||
{ |
||||
return EMPTY_SET; |
||||
} |
||||
|
||||
return new DLSet(v); |
||||
} |
||||
} |
@ -1,26 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* Stream that outputs encoding based on definite length. |
||||
*/ |
||||
class DLOutputStream |
||||
extends ASN1OutputStream |
||||
{ |
||||
DLOutputStream(OutputStream os) |
||||
{ |
||||
super(os); |
||||
} |
||||
|
||||
void writePrimitive(ASN1Primitive primitive, boolean withTag) throws IOException |
||||
{ |
||||
primitive.toDLObject().encode(this, withTag); |
||||
} |
||||
|
||||
ASN1OutputStream getDLSubStream() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,131 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* The DLSequence encodes a SEQUENCE using definite length form. |
||||
*/ |
||||
public class DLSequence |
||||
extends ASN1Sequence |
||||
{ |
||||
private int bodyLength = -1; |
||||
|
||||
/** |
||||
* Create an empty sequence |
||||
*/ |
||||
public DLSequence() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* create a sequence containing one object |
||||
* @param element the object to go in the sequence. |
||||
*/ |
||||
public DLSequence(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* create a sequence containing a vector of objects. |
||||
* @param elementVector the vector of objects to make up the sequence. |
||||
*/ |
||||
public DLSequence(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector); |
||||
} |
||||
|
||||
/** |
||||
* create a sequence containing an array of objects. |
||||
* @param elements the array of objects to make up the sequence. |
||||
*/ |
||||
public DLSequence(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements); |
||||
} |
||||
|
||||
DLSequence(ASN1Encodable[] elements, boolean clone) |
||||
{ |
||||
super(elements, clone); |
||||
} |
||||
|
||||
private int getBodyLength() throws IOException |
||||
{ |
||||
if (bodyLength < 0) |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive dlObject = elements[i].toASN1Primitive().toDLObject(); |
||||
totalLength += dlObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
} |
||||
|
||||
return bodyLength; |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int length = getBodyLength(); |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
/** |
||||
* A note on the implementation: |
||||
* <p> |
||||
* As DL requires the constructed, definite-length model to |
||||
* be used for structured types, this varies slightly from the |
||||
* ASN.1 descriptions given. Rather than just outputting SEQUENCE, |
||||
* we also have to specify CONSTRUCTED, and the objects length. |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED); |
||||
} |
||||
|
||||
ASN1OutputStream dlOut = out.getDLSubStream(); |
||||
|
||||
int count = elements.length; |
||||
if (bodyLength >= 0 || count > 16) |
||||
{ |
||||
out.writeLength(getBodyLength()); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
dlOut.writePrimitive(elements[i].toASN1Primitive(), true); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
int totalLength = 0; |
||||
|
||||
ASN1Primitive[] dlObjects = new ASN1Primitive[count]; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive dlObject = elements[i].toASN1Primitive().toDLObject(); |
||||
dlObjects[i] = dlObject; |
||||
totalLength += dlObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
out.writeLength(totalLength); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
dlOut.writePrimitive(dlObjects[i], true); |
||||
} |
||||
} |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser class for DL SEQUENCEs. |
||||
* |
||||
* TODO The class is only publicly visible to support 'instanceof' checks; provide an alternative |
||||
*/ |
||||
public class DLSequenceParser |
||||
implements ASN1SequenceParser |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
DLSequenceParser(ASN1StreamParser parser) |
||||
{ |
||||
this._parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Return the next object in the SEQUENCE. |
||||
* |
||||
* @return next object in SEQUENCE. |
||||
* @throws IOException if there is an issue loading the object. |
||||
*/ |
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in memory, encodable, representation of the SEQUENCE. |
||||
* |
||||
* @return a DLSequence. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new DLSequence(_parser.readVector()); |
||||
} |
||||
|
||||
/** |
||||
* Return a DLSequence representing this parser and its contents. |
||||
* |
||||
* @return a DLSequence. |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new IllegalStateException(e.getMessage()); |
||||
} |
||||
} |
||||
} |
@ -1,173 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* The DLSet encodes ASN.1 SET value without element ordering, |
||||
* and always using definite length form. |
||||
* <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 — The order of data values in a set value is not significant, |
||||
* and places no constraints on the order during transfer |
||||
* </blockquote> |
||||
* <h3>9: Canonical encoding rules</h3> |
||||
* <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.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 — 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. |
||||
*/ |
||||
public class DLSet |
||||
extends ASN1Set |
||||
{ |
||||
private int bodyLength = -1; |
||||
|
||||
/** |
||||
* create an empty set |
||||
*/ |
||||
public DLSet() |
||||
{ |
||||
} |
||||
|
||||
/** |
||||
* @param element - a single object that makes up the set. |
||||
*/ |
||||
public DLSet(ASN1Encodable element) |
||||
{ |
||||
super(element); |
||||
} |
||||
|
||||
/** |
||||
* @param elementVector - a vector of objects making up the set. |
||||
*/ |
||||
public DLSet(ASN1EncodableVector elementVector) |
||||
{ |
||||
super(elementVector, false); |
||||
} |
||||
|
||||
/** |
||||
* create a set from an array of objects. |
||||
*/ |
||||
public DLSet(ASN1Encodable[] elements) |
||||
{ |
||||
super(elements, false); |
||||
} |
||||
|
||||
DLSet(boolean isSorted, ASN1Encodable[] elements) |
||||
{ |
||||
super(isSorted, elements); |
||||
} |
||||
|
||||
private int getBodyLength() throws IOException |
||||
{ |
||||
if (bodyLength < 0) |
||||
{ |
||||
int count = elements.length; |
||||
int totalLength = 0; |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive dlObject = elements[i].toASN1Primitive().toDLObject(); |
||||
totalLength += dlObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
} |
||||
|
||||
return bodyLength; |
||||
} |
||||
|
||||
int encodedLength() throws IOException |
||||
{ |
||||
int length = getBodyLength(); |
||||
|
||||
return 1 + StreamUtil.calculateBodyLength(length) + length; |
||||
} |
||||
|
||||
/** |
||||
* A note on the implementation: |
||||
* <p> |
||||
* As DL requires the constructed, definite-length model to |
||||
* be used for structured types, this varies slightly from the |
||||
* ASN.1 descriptions given. Rather than just outputting SET, |
||||
* we also have to specify CONSTRUCTED, and the objects length. |
||||
*/ |
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
if (withTag) |
||||
{ |
||||
out.write(BERTags.SET | BERTags.CONSTRUCTED); |
||||
} |
||||
|
||||
ASN1OutputStream dlOut = out.getDLSubStream(); |
||||
|
||||
int count = elements.length; |
||||
if (bodyLength >= 0 || count > 16) |
||||
{ |
||||
out.writeLength(getBodyLength()); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
dlOut.writePrimitive(elements[i].toASN1Primitive(), true); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
int totalLength = 0; |
||||
|
||||
ASN1Primitive[] dlObjects = new ASN1Primitive[count]; |
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
ASN1Primitive dlObject = elements[i].toASN1Primitive().toDLObject(); |
||||
dlObjects[i] = dlObject; |
||||
totalLength += dlObject.encodedLength(); |
||||
} |
||||
|
||||
this.bodyLength = totalLength; |
||||
out.writeLength(totalLength); |
||||
|
||||
for (int i = 0; i < count; ++i) |
||||
{ |
||||
dlOut.writePrimitive(dlObjects[i], true); |
||||
} |
||||
} |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,60 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Parser class for DL SETs. |
||||
* |
||||
* TODO The class is only publicly visible to support 'instanceof' checks; provide an alternative |
||||
*/ |
||||
public class DLSetParser |
||||
implements ASN1SetParser |
||||
{ |
||||
private ASN1StreamParser _parser; |
||||
|
||||
DLSetParser(ASN1StreamParser parser) |
||||
{ |
||||
this._parser = parser; |
||||
} |
||||
|
||||
/** |
||||
* Return the next object in the SET. |
||||
* |
||||
* @return next object in SET. |
||||
* @throws IOException if there is an issue loading the object. |
||||
*/ |
||||
public ASN1Encodable readObject() |
||||
throws IOException |
||||
{ |
||||
return _parser.readObject(); |
||||
} |
||||
|
||||
/** |
||||
* Return an in memory, encodable, representation of the SET. |
||||
* |
||||
* @return a DLSet. |
||||
* @throws IOException if there is an issue loading the data. |
||||
*/ |
||||
public ASN1Primitive getLoadedObject() |
||||
throws IOException |
||||
{ |
||||
return new DLSet(_parser.readVector()); |
||||
} |
||||
|
||||
/** |
||||
* Return a DLSet representing this parser and its contents. |
||||
* |
||||
* @return a DLSet |
||||
*/ |
||||
public ASN1Primitive toASN1Primitive() |
||||
{ |
||||
try |
||||
{ |
||||
return getLoadedObject(); |
||||
} |
||||
catch (IOException e) |
||||
{ |
||||
throw new ASN1ParsingException(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
@ -1,73 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Definite Length 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 DLTaggedObject |
||||
extends ASN1TaggedObject |
||||
{ |
||||
/** |
||||
* @param explicit true if an explicitly tagged object. |
||||
* @param tagNo the tag number for this object. |
||||
* @param obj the tagged object. |
||||
*/ |
||||
public DLTaggedObject( |
||||
boolean explicit, |
||||
int tagNo, |
||||
ASN1Encodable obj) |
||||
{ |
||||
super(explicit, tagNo, obj); |
||||
} |
||||
|
||||
boolean isConstructed() |
||||
{ |
||||
return explicit || obj.toASN1Primitive().toDLObject().isConstructed(); |
||||
} |
||||
|
||||
int encodedLength() |
||||
throws IOException |
||||
{ |
||||
int length = obj.toASN1Primitive().toDLObject().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; |
||||
} |
||||
} |
||||
|
||||
void encode(ASN1OutputStream out, boolean withTag) throws IOException |
||||
{ |
||||
ASN1Primitive primitive = obj.toASN1Primitive().toDLObject(); |
||||
|
||||
int flags = BERTags.TAGGED; |
||||
if (explicit || primitive.isConstructed()) |
||||
{ |
||||
flags |= BERTags.CONSTRUCTED; |
||||
} |
||||
|
||||
out.writeTag(withTag, flags, tagNo); |
||||
|
||||
if (explicit) |
||||
{ |
||||
out.writeLength(primitive.encodedLength()); |
||||
} |
||||
|
||||
out.getDLSubStream().writePrimitive(primitive, explicit); |
||||
} |
||||
|
||||
ASN1Primitive toDLObject() |
||||
{ |
||||
return this; |
||||
} |
||||
} |
@ -1,80 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Locale; |
||||
import java.util.Map; |
||||
|
||||
class DateUtil |
||||
{ |
||||
private static Long ZERO = longValueOf(0); |
||||
|
||||
private static final Map localeCache = new HashMap(); |
||||
|
||||
static Locale EN_Locale = forEN(); |
||||
|
||||
private static Locale forEN() |
||||
{ |
||||
if ("en".equalsIgnoreCase(Locale.getDefault().getLanguage())) |
||||
{ |
||||
return Locale.getDefault(); |
||||
} |
||||
|
||||
Locale[] locales = Locale.getAvailableLocales(); |
||||
for (int i = 0; i != locales.length; i++) |
||||
{ |
||||
if ("en".equalsIgnoreCase(locales[i].getLanguage())) |
||||
{ |
||||
return locales[i]; |
||||
} |
||||
} |
||||
|
||||
return Locale.getDefault(); |
||||
} |
||||
|
||||
static Date epochAdjust(Date date) |
||||
throws ParseException |
||||
{ |
||||
Locale locale = Locale.getDefault(); |
||||
if (locale == null) |
||||
{ |
||||
return date; |
||||
} |
||||
|
||||
synchronized (localeCache) |
||||
{ |
||||
Long adj = (Long)localeCache.get(locale); |
||||
|
||||
if (adj == null) |
||||
{ |
||||
SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); |
||||
long v = dateF.parse("19700101000000GMT+00:00").getTime(); |
||||
|
||||
if (v == 0) |
||||
{ |
||||
adj = ZERO; |
||||
} |
||||
else |
||||
{ |
||||
adj = longValueOf(v); |
||||
} |
||||
|
||||
localeCache.put(locale, adj); |
||||
} |
||||
|
||||
if (adj != ZERO) |
||||
{ |
||||
return new Date(date.getTime() - adj.longValue()); |
||||
} |
||||
|
||||
return date; |
||||
} |
||||
} |
||||
|
||||
private static Long longValueOf(long v) |
||||
{ |
||||
return Long.valueOf(v); |
||||
} |
||||
} |
@ -1,144 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.EOFException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import com.fr.third.org.bouncycastle.util.io.Streams; |
||||
|
||||
/** |
||||
* Parse data stream of expected ASN.1 data expecting definite-length encoding.. |
||||
*/ |
||||
class DefiniteLengthInputStream |
||||
extends LimitedInputStream |
||||
{ |
||||
private static final byte[] EMPTY_BYTES = new byte[0]; |
||||
|
||||
private final int _originalLength; |
||||
|
||||
private int _remaining; |
||||
|
||||
DefiniteLengthInputStream( |
||||
InputStream in, |
||||
int length, |
||||
int limit) |
||||
{ |
||||
super(in, limit); |
||||
|
||||
if (length < 0) |
||||
{ |
||||
throw new IllegalArgumentException("negative lengths not allowed"); |
||||
} |
||||
|
||||
this._originalLength = length; |
||||
this._remaining = length; |
||||
|
||||
if (length == 0) |
||||
{ |
||||
setParentEofDetect(true); |
||||
} |
||||
} |
||||
|
||||
int getRemaining() |
||||
{ |
||||
return _remaining; |
||||
} |
||||
|
||||
public int read() |
||||
throws IOException |
||||
{ |
||||
if (_remaining == 0) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
int b = _in.read(); |
||||
|
||||
if (b < 0) |
||||
{ |
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining); |
||||
} |
||||
|
||||
if (--_remaining == 0) |
||||
{ |
||||
setParentEofDetect(true); |
||||
} |
||||
|
||||
return b; |
||||
} |
||||
|
||||
public int read(byte[] buf, int off, int len) |
||||
throws IOException |
||||
{ |
||||
if (_remaining == 0) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
int toRead = Math.min(len, _remaining); |
||||
int numRead = _in.read(buf, off, toRead); |
||||
|
||||
if (numRead < 0) |
||||
{ |
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining); |
||||
} |
||||
|
||||
if ((_remaining -= numRead) == 0) |
||||
{ |
||||
setParentEofDetect(true); |
||||
} |
||||
|
||||
return numRead; |
||||
} |
||||
|
||||
void readAllIntoByteArray(byte[] buf) |
||||
throws IOException |
||||
{ |
||||
if (_remaining != buf.length) |
||||
{ |
||||
throw new IllegalArgumentException("buffer length not right for data"); |
||||
} |
||||
|
||||
if (_remaining == 0) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
// make sure it's safe to do this!
|
||||
int limit = getLimit(); |
||||
if (_remaining >= limit) |
||||
{ |
||||
throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit); |
||||
} |
||||
|
||||
if ((_remaining -= Streams.readFully(_in, buf)) != 0) |
||||
{ |
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining); |
||||
} |
||||
setParentEofDetect(true); |
||||
} |
||||
|
||||
byte[] toByteArray() |
||||
throws IOException |
||||
{ |
||||
if (_remaining == 0) |
||||
{ |
||||
return EMPTY_BYTES; |
||||
} |
||||
|
||||
// make sure it's safe to do this!
|
||||
int limit = getLimit(); |
||||
if (_remaining >= limit) |
||||
{ |
||||
throw new IOException("corrupted stream - out of bounds length found: " + _remaining + " >= " + limit); |
||||
} |
||||
|
||||
byte[] bytes = new byte[_remaining]; |
||||
if ((_remaining -= Streams.readFully(_in, bytes)) != 0) |
||||
{ |
||||
throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining); |
||||
} |
||||
setParentEofDetect(true); |
||||
return bytes; |
||||
} |
||||
} |
@ -1,17 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* Interface implemented by objects that can be converted from streaming to in-memory objects. |
||||
*/ |
||||
public interface InMemoryRepresentable |
||||
{ |
||||
/** |
||||
* Get the in-memory representation of the ASN.1 object. |
||||
* @return an ASN1Primitive representing the loaded object. |
||||
* @throws IOException for bad input data. |
||||
*/ |
||||
ASN1Primitive getLoadedObject() |
||||
throws IOException; |
||||
} |
@ -1,111 +0,0 @@
|
||||
package com.fr.third.org.bouncycastle.asn1; |
||||
|
||||
import java.io.EOFException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
class IndefiniteLengthInputStream |
||||
extends LimitedInputStream |
||||
{ |
||||
private int _b1; |
||||
private int _b2; |
||||
private boolean _eofReached = false; |
||||
private boolean _eofOn00 = true; |
||||
|
||||
IndefiniteLengthInputStream( |
||||
InputStream in, |
||||
int limit) |
||||
throws IOException |
||||
{ |
||||
super(in, limit); |
||||
|
||||
_b1 = in.read(); |
||||
_b2 = in.read(); |
||||
|
||||
if (_b2 < 0) |
||||
{ |
||||
// Corrupted stream
|
||||
throw new EOFException(); |
||||
} |
||||
|
||||
checkForEof(); |
||||
} |
||||
|
||||
void setEofOn00( |
||||
boolean eofOn00) |
||||
{ |
||||
_eofOn00 = eofOn00; |
||||
checkForEof(); |
||||
} |
||||
|
||||
private boolean checkForEof() |
||||
{ |
||||
if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00)) |
||||
{ |
||||
_eofReached = true; |
||||
setParentEofDetect(true); |
||||
} |
||||
return _eofReached; |
||||
} |
||||
|
||||
public int read(byte[] b, int off, int len) |
||||
throws IOException |
||||
{ |
||||
// Only use this optimisation if we aren't checking for 00
|
||||
if (_eofOn00 || len < 3) |
||||
{ |
||||
return super.read(b, off, len); |
||||
} |
||||
|
||||
if (_eofReached) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
int numRead = _in.read(b, off + 2, len - 2); |
||||
|
||||
if (numRead < 0) |
||||
{ |
||||
// Corrupted stream
|
||||
throw new EOFException(); |
||||
} |
||||
|
||||
b[off] = (byte)_b1; |
||||
b[off + 1] = (byte)_b2; |
||||
|
||||
_b1 = _in.read(); |
||||
_b2 = _in.read(); |
||||
|
||||
if (_b2 < 0) |
||||
{ |
||||
// Corrupted stream
|
||||
throw new EOFException(); |
||||
} |
||||
|
||||
return numRead + 2; |
||||
} |
||||
|
||||
public int read() |
||||
throws IOException |
||||
{ |
||||
if (checkForEof()) |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
int b = _in.read(); |
||||
|
||||
if (b < 0) |
||||
{ |
||||
// Corrupted stream
|
||||
throw new EOFException(); |
||||
} |
||||
|
||||
int v = _b1; |
||||
|
||||
_b1 = _b2; |
||||
_b2 = b; |
||||
|
||||
return v; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue