diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-05-31 11:07:45 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-05-31 11:07:45 +0400 |
commit | 2b976f5364cfdbc37d3086019d93483c983eb80b (patch) | |
tree | cb846af3fd1d43f9c2562a1fb2d06b997ad8f229 /core/src/main/java/org/bouncycastle/util/io | |
parent | 5f714bd92fbd780d22406f4bc3681be005f6f04a (diff) |
initial reshuffle
Diffstat (limited to 'core/src/main/java/org/bouncycastle/util/io')
11 files changed, 602 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java b/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java new file mode 100644 index 00000000..01af8da9 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/StreamOverflowException.java @@ -0,0 +1,12 @@ +package org.bouncycastle.util.io; + +import java.io.IOException; + +public class StreamOverflowException + extends IOException +{ + public StreamOverflowException(String msg) + { + super(msg); + } +} diff --git a/core/src/main/java/org/bouncycastle/util/io/Streams.java b/core/src/main/java/org/bouncycastle/util/io/Streams.java new file mode 100644 index 00000000..41560b5d --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/Streams.java @@ -0,0 +1,87 @@ +package org.bouncycastle.util.io; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public final class Streams +{ + private static int BUFFER_SIZE = 512; + + public static void drain(InputStream inStr) + throws IOException + { + byte[] bs = new byte[BUFFER_SIZE]; + while (inStr.read(bs, 0, bs.length) >= 0) + { + } + } + + public static byte[] readAll(InputStream inStr) + throws IOException + { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + pipeAll(inStr, buf); + return buf.toByteArray(); + } + + public static byte[] readAllLimited(InputStream inStr, int limit) + throws IOException + { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + pipeAllLimited(inStr, limit, buf); + return buf.toByteArray(); + } + + public static int readFully(InputStream inStr, byte[] buf) + throws IOException + { + return readFully(inStr, buf, 0, buf.length); + } + + public static int readFully(InputStream inStr, byte[] buf, int off, int len) + throws IOException + { + int totalRead = 0; + while (totalRead < len) + { + int numRead = inStr.read(buf, off + totalRead, len - totalRead); + if (numRead < 0) + { + break; + } + totalRead += numRead; + } + return totalRead; + } + + public static void pipeAll(InputStream inStr, OutputStream outStr) + throws IOException + { + byte[] bs = new byte[BUFFER_SIZE]; + int numRead; + while ((numRead = inStr.read(bs, 0, bs.length)) >= 0) + { + outStr.write(bs, 0, numRead); + } + } + + public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr) + throws IOException + { + long total = 0; + byte[] bs = new byte[BUFFER_SIZE]; + int numRead; + while ((numRead = inStr.read(bs, 0, bs.length)) >= 0) + { + total += numRead; + if (total > limit) + { + throw new StreamOverflowException("Data Overflow"); + } + outStr.write(bs, 0, numRead); + } + return total; + } +} diff --git a/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java b/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java new file mode 100644 index 00000000..91542469 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/TeeInputStream.java @@ -0,0 +1,62 @@ +package org.bouncycastle.util.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class TeeInputStream + extends InputStream +{ + private final InputStream input; + private final OutputStream output; + + public TeeInputStream(InputStream input, OutputStream output) + { + this.input = input; + this.output = output; + } + + public int read(byte[] buf) + throws IOException + { + return read(buf, 0, buf.length); + } + + public int read(byte[] buf, int off, int len) + throws IOException + { + int i = input.read(buf, off, len); + + if (i > 0) + { + output.write(buf, off, i); + } + + return i; + } + + public int read() + throws IOException + { + int i = input.read(); + + if (i >= 0) + { + output.write(i); + } + + return i; + } + + public void close() + throws IOException + { + this.input.close(); + this.output.close(); + } + + public OutputStream getOutputStream() + { + return output; + } +} diff --git a/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java b/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java new file mode 100644 index 00000000..a4919cd8 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/TeeOutputStream.java @@ -0,0 +1,52 @@ +package org.bouncycastle.util.io; + +import java.io.IOException; +import java.io.OutputStream; + +public class TeeOutputStream + extends OutputStream +{ + private OutputStream output1; + private OutputStream output2; + + public TeeOutputStream(OutputStream output1, OutputStream output2) + { + this.output1 = output1; + this.output2 = output2; + } + + public void write(byte[] buf) + throws IOException + { + this.output1.write(buf); + this.output2.write(buf); + } + + public void write(byte[] buf, int off, int len) + throws IOException + { + this.output1.write(buf, off, len); + this.output2.write(buf, off, len); + } + + public void write(int b) + throws IOException + { + this.output1.write(b); + this.output2.write(b); + } + + public void flush() + throws IOException + { + this.output1.flush(); + this.output2.flush(); + } + + public void close() + throws IOException + { + this.output1.close(); + this.output2.close(); + } +}
\ No newline at end of file diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java new file mode 100644 index 00000000..69a773e7 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemGenerationException.java @@ -0,0 +1,25 @@ +package org.bouncycastle.util.io.pem; + +import java.io.IOException; + +public class PemGenerationException + extends IOException +{ + private Throwable cause; + + public PemGenerationException(String message, Throwable cause) + { + super(message); + this.cause = cause; + } + + public PemGenerationException(String message) + { + super(message); + } + + public Throwable getCause() + { + return cause; + } +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java new file mode 100644 index 00000000..b201c134 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemHeader.java @@ -0,0 +1,66 @@ +package org.bouncycastle.util.io.pem; + +public class PemHeader +{ + private String name; + private String value; + + public PemHeader(String name, String value) + { + this.name = name; + this.value = value; + } + + public String getName() + { + return name; + } + + public String getValue() + { + return value; + } + + public int hashCode() + { + return getHashCode(this.name) + 31 * getHashCode(this.value); + } + + public boolean equals(Object o) + { + if (!(o instanceof PemHeader)) + { + return false; + } + + PemHeader other = (PemHeader)o; + + return other == this || (isEqual(this.name, other.name) && isEqual(this.value, other.value)); + } + + private int getHashCode(String s) + { + if (s == null) + { + return 1; + } + + return s.hashCode(); + } + + private boolean isEqual(String s1, String s2) + { + if (s1 == s2) + { + return true; + } + + if (s1 == null || s2 == null) + { + return false; + } + + return s1.equals(s2); + } + +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java new file mode 100644 index 00000000..2199520b --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemObject.java @@ -0,0 +1,61 @@ +package org.bouncycastle.util.io.pem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class PemObject + implements PemObjectGenerator +{ + private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList()); + + private String type; + private List headers; + private byte[] content; + + /** + * Generic constructor for object without headers. + * + * @param type pem object type. + * @param content the binary content of the object. + */ + public PemObject(String type, byte[] content) + { + this(type, EMPTY_LIST, content); + } + + /** + * Generic constructor for object with headers. + * + * @param type pem object type. + * @param headers a list of PemHeader objects. + * @param content the binary content of the object. + */ + public PemObject(String type, List headers, byte[] content) + { + this.type = type; + this.headers = Collections.unmodifiableList(headers); + this.content = content; + } + + public String getType() + { + return type; + } + + public List getHeaders() + { + return headers; + } + + public byte[] getContent() + { + return content; + } + + public PemObject generate() + throws PemGenerationException + { + return this; + } +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java new file mode 100644 index 00000000..6fffdc58 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectGenerator.java @@ -0,0 +1,7 @@ +package org.bouncycastle.util.io.pem; + +public interface PemObjectGenerator +{ + PemObject generate() + throws PemGenerationException; +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java new file mode 100644 index 00000000..b18b5505 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemObjectParser.java @@ -0,0 +1,9 @@ +package org.bouncycastle.util.io.pem; + +import java.io.IOException; + +public interface PemObjectParser +{ + Object parseObject(PemObject obj) + throws IOException; +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java new file mode 100644 index 00000000..76647257 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemReader.java @@ -0,0 +1,84 @@ +package org.bouncycastle.util.io.pem; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +import org.bouncycastle.util.encoders.Base64; + +public class PemReader + extends BufferedReader +{ + private static final String BEGIN = "-----BEGIN "; + private static final String END = "-----END "; + + public PemReader(Reader reader) + { + super(reader); + } + + public PemObject readPemObject() + throws IOException + { + String line = readLine(); + + while (line != null && !line.startsWith(BEGIN)) + { + line = readLine(); + } + + if (line != null) + { + line = line.substring(BEGIN.length()); + int index = line.indexOf('-'); + String type = line.substring(0, index); + + if (index > 0) + { + return loadObject(type); + } + } + + return null; + } + + private PemObject loadObject(String type) + throws IOException + { + String line; + String endMarker = END + type; + StringBuffer buf = new StringBuffer(); + List headers = new ArrayList(); + + while ((line = readLine()) != null) + { + if (line.indexOf(":") >= 0) + { + int index = line.indexOf(':'); + String hdr = line.substring(0, index); + String value = line.substring(index + 1).trim(); + + headers.add(new PemHeader(hdr, value)); + + continue; + } + + if (line.indexOf(endMarker) != -1) + { + break; + } + + buf.append(line.trim()); + } + + if (line == null) + { + throw new IOException(endMarker + " not found"); + } + + return new PemObject(type, headers, Base64.decode(buf.toString())); + } + +} diff --git a/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java b/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java new file mode 100644 index 00000000..ccefa36e --- /dev/null +++ b/core/src/main/java/org/bouncycastle/util/io/pem/PemWriter.java @@ -0,0 +1,137 @@ +package org.bouncycastle.util.io.pem; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Iterator; + +import org.bouncycastle.util.encoders.Base64; + +/** + * A generic PEM writer, based on RFC 1421 + */ +public class PemWriter + extends BufferedWriter +{ + private static final int LINE_LENGTH = 64; + + private final int nlLength; + private char[] buf = new char[LINE_LENGTH]; + + /** + * Base constructor. + * + * @param out output stream to use. + */ + public PemWriter(Writer out) + { + super(out); + + String nl = System.getProperty("line.separator"); + if (nl != null) + { + nlLength = nl.length(); + } + else + { + nlLength = 2; + } + } + + /** + * Return the number of bytes or characters required to contain the + * passed in object if it is PEM encoded. + * + * @param obj pem object to be output + * @return an estimate of the number of bytes + */ + public int getOutputSize(PemObject obj) + { + // BEGIN and END boundaries. + int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4; + + if (!obj.getHeaders().isEmpty()) + { + for (Iterator it = obj.getHeaders().iterator(); it.hasNext();) + { + PemHeader hdr = (PemHeader)it.next(); + + size += hdr.getName().length() + ": ".length() + hdr.getValue().length() + nlLength; + } + + size += nlLength; + } + + // base64 encoding + int dataLen = ((obj.getContent().length + 2) / 3) * 4; + + size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength); + + return size; + } + + public void writeObject(PemObjectGenerator objGen) + throws IOException + { + PemObject obj = objGen.generate(); + + writePreEncapsulationBoundary(obj.getType()); + + if (!obj.getHeaders().isEmpty()) + { + for (Iterator it = obj.getHeaders().iterator(); it.hasNext();) + { + PemHeader hdr = (PemHeader)it.next(); + + this.write(hdr.getName()); + this.write(": "); + this.write(hdr.getValue()); + this.newLine(); + } + + this.newLine(); + } + + writeEncoded(obj.getContent()); + writePostEncapsulationBoundary(obj.getType()); + } + + private void writeEncoded(byte[] bytes) + throws IOException + { + bytes = Base64.encode(bytes); + + for (int i = 0; i < bytes.length; i += buf.length) + { + int index = 0; + + while (index != buf.length) + { + if ((i + index) >= bytes.length) + { + break; + } + buf[index] = (char)bytes[i + index]; + index++; + } + this.write(buf, 0, index); + this.newLine(); + } + } + + private void writePreEncapsulationBoundary( + String type) + throws IOException + { + this.write("-----BEGIN " + type + "-----"); + this.newLine(); + } + + private void writePostEncapsulationBoundary( + String type) + throws IOException + { + this.write("-----END " + type + "-----"); + this.newLine(); + } +} |