Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/spongycastle/util/io/pem')
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java28
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java75
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObject.java64
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java16
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java19
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemReader.java87
-rw-r--r--core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java137
7 files changed, 426 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java b/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
new file mode 100644
index 00000000..676b82d1
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemGenerationException.java
@@ -0,0 +1,28 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown on failure to generate a PEM object.
+ */
+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/spongycastle/util/io/pem/PemHeader.java b/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
new file mode 100644
index 00000000..14293267
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemHeader.java
@@ -0,0 +1,75 @@
+package org.spongycastle.util.io.pem;
+
+/**
+ * Class representing a PEM header (name, value) pair.
+ */
+public class PemHeader
+{
+ private String name;
+ private String value;
+
+ /**
+ * Base constructor.
+ *
+ * @param name name of the header property.
+ * @param value value of the header property.
+ */
+ 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/spongycastle/util/io/pem/PemObject.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java
new file mode 100644
index 00000000..16c5c4f5
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObject.java
@@ -0,0 +1,64 @@
+package org.spongycastle.util.io.pem;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A generic PEM object - type, header properties, and byte content.
+ */
+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/spongycastle/util/io/pem/PemObjectGenerator.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
new file mode 100644
index 00000000..0df180ce
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectGenerator.java
@@ -0,0 +1,16 @@
+package org.spongycastle.util.io.pem;
+
+/**
+ * Base interface for generators of PEM objects.
+ */
+public interface PemObjectGenerator
+{
+ /**
+ * Generate a PEM object.
+ *
+ * @return the generated object.
+ * @throws PemGenerationException on failure.
+ */
+ PemObject generate()
+ throws PemGenerationException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java
new file mode 100644
index 00000000..5192078f
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemObjectParser.java
@@ -0,0 +1,19 @@
+package org.spongycastle.util.io.pem;
+
+import java.io.IOException;
+
+/**
+ * Base interface for parsers to convert PEM objects into specific objects.
+ */
+public interface PemObjectParser
+{
+ /**
+ * Parse an object out of the PEM object passed in.
+ *
+ * @param obj the PEM object containing the details for the specific object.
+ * @return a specific object represented by the PEM object.
+ * @throws IOException on a parsing error.
+ */
+ Object parseObject(PemObject obj)
+ throws IOException;
+}
diff --git a/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java b/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java
new file mode 100644
index 00000000..0b909167
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemReader.java
@@ -0,0 +1,87 @@
+package org.spongycastle.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.spongycastle.util.encoders.Base64;
+
+/**
+ * A generic PEM reader, based on the format outlined in RFC 1421
+ */
+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/spongycastle/util/io/pem/PemWriter.java b/core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
new file mode 100644
index 00000000..02dde96b
--- /dev/null
+++ b/core/src/main/java/org/spongycastle/util/io/pem/PemWriter.java
@@ -0,0 +1,137 @@
+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
+ */
+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();
+ }
+}