KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > security > SecureFileStore


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.security;
6
7 import java.sql.SQLException JavaDoc;
8
9 import org.h2.engine.Constants;
10 import org.h2.message.Message;
11 import org.h2.store.DataHandler;
12 import org.h2.store.FileStore;
13 import org.h2.util.RandomUtils;
14
15 public class SecureFileStore extends FileStore {
16
17     private byte[] key;
18     private BlockCipher cipher;
19     private BlockCipher cipherForInitVector;
20     private byte[] buffer = new byte[4];
21     private long pos;
22     private byte[] bufferForInitVector;
23     private int keyIterations;
24
25     public SecureFileStore(DataHandler handler, String JavaDoc name, byte[] magic, String JavaDoc cipher, byte[] key, int keyIterations) throws SQLException JavaDoc {
26         super(handler, name, magic);
27         this.key = key;
28         if ("XTEA".equalsIgnoreCase(cipher)) {
29             this.cipher = new XTEA();
30             this.cipherForInitVector = new XTEA();
31         } else if ("AES".equalsIgnoreCase(cipher)) {
32             this.cipher = new AES();
33             this.cipherForInitVector = new AES();
34         } else {
35             throw Message.getSQLException(Message.UNSUPPORTED_CIPHER, cipher);
36         }
37         this.keyIterations = keyIterations;
38         bufferForInitVector = new byte[Constants.FILE_BLOCK_SIZE];
39     }
40
41     protected byte[] generateSalt() {
42         return RandomUtils.getSecureBytes(Constants.FILE_BLOCK_SIZE);
43     }
44
45     protected void initKey(byte[] salt) {
46         SHA256 sha = new SHA256();
47         key = sha.getHashWithSalt(key, salt);
48         for (int i = 0; i < keyIterations; i++) {
49             key = sha.getHash(key);
50         }
51         cipher.setKey(key);
52         key = sha.getHash(key);
53         cipherForInitVector.setKey(key);
54     }
55
56     protected void writeDirect(byte[] b, int off, int len) throws SQLException JavaDoc {
57         super.write(b, off, len);
58         pos += len;
59     }
60
61     public void write(byte[] b, int off, int len) throws SQLException JavaDoc {
62         if (buffer.length < b.length) {
63             buffer = new byte[len];
64         }
65         System.arraycopy(b, off, buffer, 0, len);
66         xorInitVector(buffer, 0, len, pos);
67         cipher.encrypt(buffer, 0, len);
68         super.write(buffer, 0, len);
69         pos += len;
70     }
71
72     protected void readFullyDirect(byte[] b, int off, int len) throws SQLException JavaDoc {
73         super.readFully(b, off, len);
74         pos += len;
75     }
76
77     public void readFully(byte[] b, int off, int len) throws SQLException JavaDoc {
78         super.readFully(b, off, len);
79         cipher.decrypt(b, off, len);
80         xorInitVector(b, off, len, pos);
81         pos += len;
82     }
83
84     public void seek(long x) throws SQLException JavaDoc {
85         this.pos = x;
86         super.seek(x);
87     }
88     
89     public void setLength(long newLength) throws SQLException JavaDoc {
90         long oldPos = pos;
91         byte[] buff = new byte[Constants.FILE_BLOCK_SIZE];
92         long length = length();
93         if(newLength > length) {
94             seek(length);
95             for(long i = length; i<newLength; i+= Constants.FILE_BLOCK_SIZE) {
96                 write(buff, 0, Constants.FILE_BLOCK_SIZE);
97             }
98             seek(oldPos);
99         } else {
100             super.setLength(newLength);
101         }
102     }
103     
104     private void xorInitVector(byte[] b, int off, int len, long pos) {
105         byte[] iv = bufferForInitVector;
106         while(len > 0) {
107             for(int i=0; i<Constants.FILE_BLOCK_SIZE; i+=8) {
108                 long block = ((pos+i) >>> 3);
109                 iv[i] = (byte) (block >> 56);
110                 iv[i+1] = (byte) (block >> 48);
111                 iv[i+2] = (byte) (block >> 40);
112                 iv[i+3] = (byte) (block >> 32);
113                 iv[i+4] = (byte) (block >> 24);
114                 iv[i+5] = (byte) (block >> 16);
115                 iv[i+6] = (byte) (block >> 8);
116                 iv[i+7] = (byte) block;
117             }
118             cipherForInitVector.encrypt(iv, 0, Constants.FILE_BLOCK_SIZE);
119             for(int i=0; i<Constants.FILE_BLOCK_SIZE; i++) {
120                 b[off + i] ^= iv[i];
121             }
122             pos += Constants.FILE_BLOCK_SIZE;
123             off += Constants.FILE_BLOCK_SIZE;
124             len -= Constants.FILE_BLOCK_SIZE;
125         }
126     }
127     
128 }
129
Popular Tags