File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\security\SecureFileStore.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.security;
8
9 import org.h2.engine.Constants;
10 import org.h2.store.DataHandler;
11 import org.h2.store.FileStore;
12 import org.h2.util.MathUtils;
13
14 /**
15 * A file store that encrypts all data before writing, and decrypts all data
16 * after reading. Areas that were never written to (for example after calling
17 * setLength to enlarge the file) are not encrypted (contains 0 bytes).
18 */
19 public class SecureFileStore extends FileStore {
20
21 private byte[] key;
22 private final BlockCipher cipher;
23 private final BlockCipher cipherForInitVector;
24 private byte[] buffer = new byte[4];
25 private long pos;
26 private final byte[] bufferForInitVector;
27 private final int keyIterations;
28
29 public SecureFileStore(DataHandler handler, String name, String mode, String cipher, byte[] key, int keyIterations) {
30 super(handler, name, mode);
31 this.key = key;
32 this.cipher = CipherFactory.getBlockCipher(cipher);
33 this.cipherForInitVector = CipherFactory.getBlockCipher(cipher);
34 this.keyIterations = keyIterations;
35 bufferForInitVector = new byte[Constants.FILE_BLOCK_SIZE];
36 }
37
38 protected byte[] generateSalt() {
39 return MathUtils.secureRandomBytes(Constants.FILE_BLOCK_SIZE);
40 }
41
42 protected void initKey(byte[] salt) {
43 key = SHA256.getHashWithSalt(key, salt);
44 for (int i = 0; i < keyIterations; i++) {
45 key = SHA256.getHash(key, true);
46 }
47 cipher.setKey(key);
48 key = SHA256.getHash(key, true);
49 cipherForInitVector.setKey(key);
50 }
51
52 protected void writeDirect(byte[] b, int off, int len) {
53 super.write(b, off, len);
54 pos += len;
55 }
56
57 public void write(byte[] b, int off, int len) {
58 if (buffer.length < b.length) {
59 buffer = new byte[len];
60 }
61 System.arraycopy(b, off, buffer, 0, len);
62 xorInitVector(buffer, 0, len, pos);
63 cipher.encrypt(buffer, 0, len);
64 super.write(buffer, 0, len);
65 pos += len;
66 }
67
68 protected void readFullyDirect(byte[] b, int off, int len) {
69 super.readFully(b, off, len);
70 pos += len;
71 }
72
73 public void readFully(byte[] b, int off, int len) {
74 super.readFully(b, off, len);
75 for (int i = 0; i < len; i++) {
76 if (b[i] != 0) {
77 cipher.decrypt(b, off, len);
78 xorInitVector(b, off, len, pos);
79 break;
80 }
81 }
82 pos += len;
83 }
84
85 public void seek(long x) {
86 this.pos = x;
87 super.seek(x);
88 }
89
90 private void xorInitVector(byte[] b, int off, int len, long p) {
91 byte[] iv = bufferForInitVector;
92 while (len > 0) {
93 for (int i = 0; i < Constants.FILE_BLOCK_SIZE; i += 8) {
94 long block = (p + i) >>> 3;
95 iv[i] = (byte) (block >> 56);
96 iv[i + 1] = (byte) (block >> 48);
97 iv[i + 2] = (byte) (block >> 40);
98 iv[i + 3] = (byte) (block >> 32);
99 iv[i + 4] = (byte) (block >> 24);
100 iv[i + 5] = (byte) (block >> 16);
101 iv[i + 6] = (byte) (block >> 8);
102 iv[i + 7] = (byte) block;
103 }
104 cipherForInitVector.encrypt(iv, 0, Constants.FILE_BLOCK_SIZE);
105 for (int i = 0; i < Constants.FILE_BLOCK_SIZE; i++) {
106 b[off + i] ^= iv[i];
107 }
108 p += Constants.FILE_BLOCK_SIZE;
109 off += Constants.FILE_BLOCK_SIZE;
110 len -= Constants.FILE_BLOCK_SIZE;
111 }
112 }
113
114 }
115