diff options
author | Arne Schwabe <arne@rfc2549.org> | 2012-06-28 19:33:05 +0200 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2012-06-28 19:33:05 +0200 |
commit | 73d3b9c032eae2074726cd3668546af1c44a8323 (patch) | |
tree | c40b4e6447efa6d1d1c8618a3f79723f29e2db14 /src/org/spongycastle/util/io/pem/PemWriter.java | |
parent | 629417eb6b9db777b0db6b36d1c8ceb4c2760f7c (diff) |
The 'be ready for Jelly Beans' commit
- fix concurrentaccess occuring on JB
- JB does not allow to extract the private keys from the key storage, rewrite using the key storage to use JAVA API and the external-key management interface
Diffstat (limited to 'src/org/spongycastle/util/io/pem/PemWriter.java')
-rw-r--r-- | src/org/spongycastle/util/io/pem/PemWriter.java | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/org/spongycastle/util/io/pem/PemWriter.java b/src/org/spongycastle/util/io/pem/PemWriter.java new file mode 100644 index 0000000..f5a6a36 --- /dev/null +++ b/src/org/spongycastle/util/io/pem/PemWriter.java @@ -0,0 +1,138 @@ +package org.spongycastle.util.io.pem; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Iterator; + +import org.spongycastle.util.encoders.Base64; + +/** + * A generic PEM writer, based on RFC 1421 + */ +@SuppressWarnings("all") +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(); + } +} |