port.org.bouncycastle.asn1.DERBitString Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dss-model Show documentation
Show all versions of dss-model Show documentation
DSS Model contains the data model representation for DSS
package port.org.bouncycastle.asn1;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import port.org.bouncycastle.util.Arrays;
import port.org.bouncycastle.util.io.Streams;
public class DERBitString extends ASN1Primitive implements ASN1String {
private static final char[] table = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
protected byte[] data;
protected int padBits;
/**
* @param bitString
* an int containing the BIT STRING
* @return the correct number of pad bits for a bit string defined in
* a 32 bit constant
*/
static protected int getPadBits(int bitString) {
int val = 0;
for (int i = 3; i >= 0; i--) {
//
// this may look a little odd, but if it isn't done like this pre jdk1.2
// JVM's break!
//
if (i != 0) {
if ((bitString >> (i * 8)) != 0) {
val = (bitString >> (i * 8)) & 0xFF;
break;
}
} else {
if (bitString != 0) {
val = bitString & 0xFF;
break;
}
}
}
if (val == 0) {
return 7;
}
int bits = 1;
while (((val <<= 1) & 0xFF) != 0) {
bits++;
}
return 8 - bits;
}
/**
* @param bitString
* an int containing the BIT STRING
* @return the correct number of bytes for a bit string defined in
* a 32 bit constant
*/
static protected byte[] getBytes(int bitString) {
int bytes = 4;
for (int i = 3; i >= 1; i--) {
if ((bitString & (0xFF << (i * 8))) != 0) {
break;
}
bytes--;
}
byte[] result = new byte[bytes];
for (int i = 0; i < bytes; i++) {
result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
}
return result;
}
/**
* return a Bit String from the passed in object
*
* @param obj
* a DERBitString or an object that can be converted into one.
* @exception IllegalArgumentException
* if the object cannot be converted.
* @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(Object obj) {
if ((obj == null) || (obj instanceof DERBitString)) {
return (DERBitString) obj;
}
throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
}
/**
* return a Bit String from a tagged object.
*
* @param obj
* the tagged object holding the object we want
* @param explicit
* true if the object is meant to be explicitly
* tagged false otherwise.
* @exception IllegalArgumentException
* if the tagged object cannot
* be converted.
* @return a DERBitString instance, or null.
*/
public static DERBitString getInstance(ASN1TaggedObject obj, boolean explicit) {
ASN1Primitive o = obj.getObject();
if (explicit || (o instanceof DERBitString)) {
return getInstance(o);
} else {
return fromOctetString(((ASN1OctetString) o).getOctets());
}
}
protected DERBitString(byte data, int padBits) {
this.data = new byte[1];
this.data[0] = data;
this.padBits = padBits;
}
/**
* @param data
* the octets making up the bit string.
* @param padBits
* the number of extra bits at the end of the string.
*/
public DERBitString(byte[] data, int padBits) {
this.data = data;
this.padBits = padBits;
}
public DERBitString(byte[] data) {
this(data, 0);
}
public DERBitString(int value) {
this.data = getBytes(value);
this.padBits = getPadBits(value);
}
public DERBitString(ASN1Encodable obj) throws IOException {
this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
this.padBits = 0;
}
public byte[] getBytes() {
return data;
}
public int getPadBits() {
return padBits;
}
/**
* @return the value of the bit string as an int (truncating if necessary)
*/
public int intValue() {
int value = 0;
for (int i = 0; (i != data.length) && (i != 4); i++) {
value |= (data[i] & 0xff) << (8 * i);
}
return value;
}
@Override
boolean isConstructed() {
return false;
}
@Override
int encodedLength() {
return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
}
@Override
void encode(ASN1OutputStream out) throws IOException {
byte[] bytes = new byte[getBytes().length + 1];
bytes[0] = (byte) getPadBits();
System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
out.writeEncoded(BERTags.BIT_STRING, bytes);
}
@Override
public int hashCode() {
return padBits ^ Arrays.hashCode(data);
}
@Override
protected boolean asn1Equals(ASN1Primitive o) {
if (!(o instanceof DERBitString)) {
return false;
}
DERBitString other = (DERBitString) o;
return (this.padBits == other.padBits) && Arrays.areEqual(this.data, other.data);
}
@Override
public String getString() {
StringBuffer buf = new StringBuffer("#");
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
try {
aOut.writeObject(this);
} catch (IOException e) {
throw new RuntimeException("internal error encoding BitString");
}
byte[] string = bOut.toByteArray();
for (int i = 0; i != string.length; i++) {
buf.append(table[(string[i] >>> 4) & 0xf]);
buf.append(table[string[i] & 0xf]);
}
return buf.toString();
}
@Override
public String toString() {
return getString();
}
static DERBitString fromOctetString(byte[] bytes) {
if (bytes.length < 1) {
throw new IllegalArgumentException("truncated BIT STRING detected");
}
int padBits = bytes[0];
byte[] data = new byte[bytes.length - 1];
if (data.length != 0) {
System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
}
return new DERBitString(data, padBits);
}
static DERBitString fromInputStream(int length, InputStream stream) throws IOException {
if (length < 1) {
throw new IllegalArgumentException("truncated BIT STRING detected");
}
int padBits = stream.read();
byte[] data = new byte[length - 1];
if (data.length != 0) {
if (Streams.readFully(stream, data) != data.length) {
throw new EOFException("EOF encountered in middle of BIT STRING");
}
}
return new DERBitString(data, padBits);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy