1
10package org.jstk.cert.rep;
11
12import java.util.Collection;
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.security.cert.Certificate;
16import java.security.cert.X509Certificate;
17import java.security.cert.X509CRL;
18import java.security.cert.CertificateFactory;
19import java.io.File;
20import java.io.InputStream;
21import java.io.FileInputStream;
22import java.io.BufferedInputStream;
23import java.io.ByteArrayInputStream;
24import java.io.OutputStream;
25import java.io.FileOutputStream;
26import java.io.BufferedOutputStream;
27
28import java.io.IOException;
29import java.io.EOFException;
30
31public class FileBasedRepository {
32 private static class FBRInput {
33 private InputStream is;
34 private int off;
35
36 public FBRInput(InputStream is){
37 this.is = is;
38 off = 0;
39 }
40
41 public int getOffset(){
42 return off;
43 }
44
45 public byte readByte() throws IOException {
46 int b = is.read();
47 if (b == -1)
48 throw new EOFException();
49 off += 1;
50 return (byte)b;
51 }
52
53 public int readInt() throws IOException {
54 int b1 = is.read();
55 int b2 = is.read();
56 int b3 = is.read();
57 int b4 = is.read();
58 if ((b1 | b2 | b3 | b4) < 0) throw new EOFException();
60 off += 4;
61 return ((b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0));
62 }
63
64 public byte[] readBytes(int len) throws IOException {
65 if (len < 0)
66 throw new IOException("Negative no. of bytes to read");
67 byte[] data = new byte[len];
68 int nRead = 0;
69 while (nRead < len){
70 int n = is.read(data, nRead, len - nRead);
71 if (n == -1)
72 throw new EOFException();
73 nRead += n;
74 off += n;
75 }
76 return data;
77 }
78 public X509Certificate readX509Certificate() throws Exception {
79 int len = readInt();
80 byte[] data = readBytes(len);
81
82 CertificateFactory cf = CertificateFactory.getInstance("X.509");
83 ByteArrayInputStream bais = new ByteArrayInputStream(data);
84 X509Certificate cert = (X509Certificate)cf.generateCertificate(bais);
85 return cert;
86 }
87 public X509CRL readX509CRL() throws Exception {
88 int len = readInt();
89 byte[] data = readBytes(len);
90
91 CertificateFactory cf = CertificateFactory.getInstance("X.509");
92 ByteArrayInputStream bais = new ByteArrayInputStream(data);
93 X509CRL crl = (X509CRL)cf.generateCRL(bais);
94 return crl;
95 }
96 }
97
98 private static class FBROutput {
99 private OutputStream os;
00 private int off;
01
02 public FBROutput(OutputStream os){
03 this.os = os;
04 off = 0;
05 }
06
07 public int getOffset(){
08 return off;
09 }
10
11 public void writeByte(byte b) throws IOException {
12 os.write(b);
13 this.off += 1;
14 }
15
16 public void writeInt(int v) throws IOException {
17 os.write((v >>> 24) & 0xFF);
18 os.write((v >>> 16) & 0xFF);
19 os.write((v >>> 8) & 0xFF);
20 os.write((v >>> 0) & 0xFF);
21 off += 4;
22 }
23
24 public void writeBytes(byte[] data, int off, int len) throws IOException {
25 os.write(data, off, len);
26 this.off += len;
27 }
28
29 public void writeX509Certificate(X509Certificate cert) throws Exception {
30 byte[] data = cert.getEncoded();
31 writeInt(data.length);
32 writeBytes(data, 0, data.length);
33 }
34 public void writeX509CRL(X509CRL crl) throws Exception {
35 byte[] data = crl.getEncoded();
36 writeInt(data.length);
37 writeBytes(data, 0, data.length);
38 }
39 }
40
41 public static final int FBREP_MAGIC = 15071968;
42 public static final byte X509CERT = 0x01;
43 public static final byte X509CRL = 0x02;
44 public static final byte FBREP_END = 0x00;
45
46 private String filename = null;
47 private ArrayList list = new ArrayList();
48 public FileBasedRepository(String filename) throws Exception {
49 this.filename = filename;
50 File file = new File(filename);
51 if (!file.exists()){ save();
53 }
54 load();
55 }
56 public Collection getRepository(){
57 return list;
58 }
59 public synchronized void load() throws Exception {
60 FileInputStream fis = new FileInputStream(filename);
61 FBRInput fbrInput = new FBRInput(fis);
62 int magicNo = fbrInput.readInt();
63 if (magicNo != FBREP_MAGIC)
64 throw new IOException("Not a File Based Repository");
65
66 list = new ArrayList();
67 boolean scanComplete = false;
68 while (!scanComplete){
69 byte entryId = fbrInput.readByte();
70 switch (entryId){
71 case X509CERT:
72 X509Certificate cert = fbrInput.readX509Certificate();
73 list.add(cert);
74 break;
75 case X509CRL:
76 X509CRL crl = fbrInput.readX509CRL();
77 list.add(crl);
78 break;
79 case FBREP_END:
80 scanComplete = true;
81 break;
82 default:
83 throw new IOException("Unexpected Data at offset = " + fbrInput.getOffset());
84 }
85 }
86
87 }
88 public synchronized void save() throws Exception {
89 FileOutputStream fos = new FileOutputStream(filename);
90 FBROutput fbrOutput = new FBROutput(fos);
91 fbrOutput.writeInt(FBREP_MAGIC);
92 Iterator itr = list.iterator();
93 while (itr.hasNext()){
94 Object entry = itr.next();
95 if (entry instanceof X509Certificate){
96 fbrOutput.writeByte(X509CERT);
97 fbrOutput.writeX509Certificate((X509Certificate)entry);
98 } else if (entry instanceof X509CRL){
99 fbrOutput.writeByte(X509CRL);
00 fbrOutput.writeX509CRL((X509CRL)entry);
01 }
02 }
03 fbrOutput.writeByte(FBREP_END);
04 }
05
06 public static void main(String[] args) throws Exception {
07 if (args.length != 1){
08 System.out.println("Usage:: java FileBasedRepository <filename>");
09 return;
10 }
11 FileBasedRepository fbr = new FileBasedRepository(args[0]);
12 }
13}
14
15