--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.store.raw.data.DecryptInputStream\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.raw.data;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.store.raw.data.DataFactory;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+\r
+import org.apache.derby.iapi.services.io.CompressedNumber;\r
+\r
+import java.io.InputStream;\r
+import java.io.IOException;\r
+\r
+/**\r
+ A DecryptInputStream is used by stream container to access an encrypted\r
+ stream of bytes.\r
+*/\r
+public class DecryptInputStream extends BufferedByteHolderInputStream {\r
+\r
+ // if database is encrypted, bytes to reserve at the beginning of the buffer\r
+ //protected static final int ENCRYPTION_RESERVE = dataFactory.getEncryptionBlockSize() - 1;\r
+\r
+ protected DataFactory dataFactory;\r
+ protected InputStream in;\r
+\r
+ public DecryptInputStream(InputStream in, ByteHolder bh, DataFactory dataFactory)\r
+ throws IOException {\r
+\r
+ super(bh);\r
+ this.in = in;\r
+ this.dataFactory = dataFactory;\r
+ fillByteHolder();\r
+ }\r
+\r
+ public void fillByteHolder() throws IOException {\r
+\r
+ if (this.bh.available() == 0) {\r
+\r
+ this.bh.clear();\r
+\r
+ try {\r
+ // from the stream, read the actual length of the bytes\r
+ // before it was padded and encrypted.\r
+ int realLen = CompressedNumber.readInt(in);\r
+ // if it is -1, we have reached the end of the file.\r
+ // then we are done.\r
+ if (realLen == -1)\r
+ return;\r
+\r
+ // calculate out what the padding was based on the actual length\r
+ int tail = realLen % dataFactory.getEncryptionBlockSize();\r
+ int padding = (tail == 0) ? 0 : (dataFactory.getEncryptionBlockSize() - tail);\r
+ int encryptedLen = realLen + padding;\r
+\r
+ // read all encrypted data including the padding.\r
+ byte[] ciphertext = new byte[encryptedLen];\r
+ in.read(ciphertext, 0, encryptedLen);\r
+ byte[] cleartext = new byte[encryptedLen];\r
+ // decrypt the data, and stored it in a new byte array.\r
+ dataFactory.decrypt(ciphertext, 0, encryptedLen, cleartext, 0);\r
+\r
+ // only put the actual data without the padding into the byte holder.\r
+ bh.write(cleartext, padding, realLen);\r
+\r
+ } catch (StandardException se) {\r
+ throw new IOException();\r
+ }\r
+\r
+ // allow reading from the byte holder.\r
+ this.bh.startReading();\r
+ }\r
+ }\r
+}\r