提交 145ab625 authored 作者: Thomas Mueller's avatar Thomas Mueller

mainly javadocs

上级 9c7fd89d
...@@ -16,7 +16,6 @@ import org.h2.constraint.ConstraintReferential; ...@@ -16,7 +16,6 @@ import org.h2.constraint.ConstraintReferential;
import org.h2.constraint.ConstraintUnique; import org.h2.constraint.ConstraintUnique;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Right; import org.h2.engine.Right;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
...@@ -75,9 +74,9 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -75,9 +74,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
super(session, schema); super(session, schema);
} }
private String generateConstraintName(DbObject obj) { private String generateConstraintName(Table table) {
if (constraintName == null) { if (constraintName == null) {
constraintName = getSchema().getUniqueConstraintName(obj); constraintName = getSchema().getUniqueConstraintName(table);
} }
return constraintName; return constraintName;
} }
......
...@@ -10,10 +10,10 @@ import java.sql.SQLException; ...@@ -10,10 +10,10 @@ import java.sql.SQLException;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn; import org.h2.expression.ExpressionColumn;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.util.ObjectArray;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueString; import org.h2.value.ValueString;
...@@ -44,10 +44,11 @@ public class ExplainPlan extends Prepared { ...@@ -44,10 +44,11 @@ public class ExplainPlan extends Prepared {
public LocalResult query(int maxrows) throws SQLException { public LocalResult query(int maxrows) throws SQLException {
// TODO rights: are rights required for explain? // TODO rights: are rights required for explain?
ObjectArray expressions = new ObjectArray();
Column column = new Column("PLAN", Value.STRING); Column column = new Column("PLAN", Value.STRING);
ExpressionColumn expr = new ExpressionColumn(session.getDatabase(), column); ExpressionColumn expr = new ExpressionColumn(session.getDatabase(), column);
expressions.add(expr); Expression[] expressions = new Expression[] {
expr
};
result = new LocalResult(session, expressions, 1); result = new LocalResult(session, expressions, 1);
if (maxrows >= 0) { if (maxrows >= 0) {
String plan = command.getPlanSQL(); String plan = command.getPlanSQL();
......
...@@ -34,6 +34,7 @@ import org.h2.engine.Setting; ...@@ -34,6 +34,7 @@ import org.h2.engine.Setting;
import org.h2.engine.User; import org.h2.engine.User;
import org.h2.engine.UserAggregate; import org.h2.engine.UserAggregate;
import org.h2.engine.UserDataType; import org.h2.engine.UserDataType;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn; import org.h2.expression.ExpressionColumn;
import org.h2.index.Cursor; import org.h2.index.Cursor;
import org.h2.index.Index; import org.h2.index.Index;
...@@ -114,9 +115,9 @@ public class ScriptCommand extends ScriptBase { ...@@ -114,9 +115,9 @@ public class ScriptCommand extends ScriptBase {
} }
private LocalResult createResult() { private LocalResult createResult() {
ObjectArray cols = new ObjectArray(); Expression[] expressions = new Expression[] { new ExpressionColumn(session.getDatabase(), new Column("SCRIPT",
cols.add(new ExpressionColumn(session.getDatabase(), new Column("SCRIPT", Value.STRING))); Value.STRING)) };
return new LocalResult(session, cols, 1); return new LocalResult(session, expressions, 1);
} }
public LocalResult query(int maxrows) throws SQLException { public LocalResult query(int maxrows) throws SQLException {
......
...@@ -1356,6 +1356,7 @@ public class Database implements DataHandler { ...@@ -1356,6 +1356,7 @@ public class Database implements DataHandler {
throw Message.getInternalError("object already exists: " + newName); throw Message.getInternalError("object already exists: " + newName);
} }
} }
obj.checkRename();
int id = obj.getId(); int id = obj.getId();
removeMeta(session, id); removeMeta(session, id);
map.remove(obj.getName()); map.remove(obj.getName());
......
...@@ -56,6 +56,12 @@ public class User extends RightOwner { ...@@ -56,6 +56,12 @@ public class User extends RightOwner {
this.passwordHash = hash; this.passwordHash = hash;
} }
/**
* Set the user name password hash. A random salt is generated as well.
* The parameter is nulled out after use.
*
* @param userPasswordHash the user name password hash
*/
public void setUserPasswordHash(byte[] userPasswordHash) { public void setUserPasswordHash(byte[] userPasswordHash) {
if (userPasswordHash != null) { if (userPasswordHash != null) {
salt = RandomUtils.getSecureBytes(Constants.SALT_LEN); salt = RandomUtils.getSecureBytes(Constants.SALT_LEN);
......
...@@ -1141,7 +1141,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1141,7 +1141,7 @@ public class Function extends Expression implements FunctionCall {
private byte[] getHash(String algorithm, byte[] bytes, int iterations) throws SQLException { private byte[] getHash(String algorithm, byte[] bytes, int iterations) throws SQLException {
SHA256 hash = CipherFactory.getHash(algorithm); SHA256 hash = CipherFactory.getHash(algorithm);
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
bytes = hash.getHash(bytes); bytes = hash.getHash(bytes, false);
} }
return bytes; return bytes;
} }
......
...@@ -46,6 +46,14 @@ public class LocalResult implements ResultInterface { ...@@ -46,6 +46,14 @@ public class LocalResult implements ResultInterface {
private boolean distinct; private boolean distinct;
private boolean closed; private boolean closed;
/**
* Construct a local result set by reading all data from a regular result set.
*
* @param session the session
* @param rs the result set
* @param maxrows the maximum number of rows to read (0 for no limit)
* @return the local result set
*/
public static LocalResult read(Session session, ResultSet rs, int maxrows) throws SQLException { public static LocalResult read(Session session, ResultSet rs, int maxrows) throws SQLException {
ObjectArray cols = getExpressionColumns(session, rs); ObjectArray cols = getExpressionColumns(session, rs);
int columnCount = cols.size(); int columnCount = cols.size();
...@@ -80,10 +88,20 @@ public class LocalResult implements ResultInterface { ...@@ -80,10 +88,20 @@ public class LocalResult implements ResultInterface {
return cols; return cols;
} }
/**
* Construct a local result object.
*/
public LocalResult() { public LocalResult() {
// nothing to do // nothing to do
} }
/**
* Construct a local result object.
*
* @param session the session
* @param expressions the expression array
* @param the number of visible columns
*/
public LocalResult(Session session, Expression[] expressions, int visibleColumnCount) { public LocalResult(Session session, Expression[] expressions, int visibleColumnCount) {
this.session = session; this.session = session;
if (session == null) { if (session == null) {
...@@ -96,7 +114,24 @@ public class LocalResult implements ResultInterface { ...@@ -96,7 +114,24 @@ public class LocalResult implements ResultInterface {
rowId = -1; rowId = -1;
this.expressions = expressions; this.expressions = expressions;
} }
/**
* Construct a local result object.
*
* @param session the session
* @param expressions the expression list
* @param the number of visible columns
*/
public LocalResult(Session session, ObjectArray expressionList, int visibleColumnCount) {
this(session, getList(expressionList), visibleColumnCount);
}
/**
* Create a shallow copy of the result set. The data and a temporary table (if there is any) is not copied.
*
* @param session the session
* @return the copy
*/
public LocalResult createShallowCopy(Session session) { public LocalResult createShallowCopy(Session session) {
if (disk == null && (rows == null || rows.size() < rowCount)) { if (disk == null && (rows == null || rows.size() < rowCount)) {
return null; return null;
...@@ -120,25 +155,34 @@ public class LocalResult implements ResultInterface { ...@@ -120,25 +155,34 @@ public class LocalResult implements ResultInterface {
return copy; return copy;
} }
public LocalResult(Session session, ObjectArray expressionList, int visibleColumnCount) {
this(session, getList(expressionList), visibleColumnCount);
}
private static Expression[] getList(ObjectArray expressionList) { private static Expression[] getList(ObjectArray expressionList) {
Expression[] expressions = new Expression[expressionList.size()]; Expression[] expressions = new Expression[expressionList.size()];
expressionList.toArray(expressions); expressionList.toArray(expressions);
return expressions; return expressions;
} }
/**
* Set the sort order.
*
* @param sort the sort order
*/
public void setSortOrder(SortOrder sort) { public void setSortOrder(SortOrder sort) {
this.sort = sort; this.sort = sort;
} }
/**
* Remove duplicate rows.
*/
public void setDistinct() { public void setDistinct() {
distinct = true; distinct = true;
distinctRows = new ValueHashMap(session.getDatabase()); distinctRows = new ValueHashMap(session.getDatabase());
} }
/**
* Remove the row from the result set if it exists.
*
* @param values the row
*/
public void removeDistinct(Value[] values) throws SQLException { public void removeDistinct(Value[] values) throws SQLException {
if (!distinct) { if (!distinct) {
throw Message.getInternalError(); throw Message.getInternalError();
...@@ -152,6 +196,12 @@ public class LocalResult implements ResultInterface { ...@@ -152,6 +196,12 @@ public class LocalResult implements ResultInterface {
} }
} }
/**
* Check if this result set contains the given row.
*
* @param values the row
* @return true if the row exists
*/
public boolean containsDistinct(Value[] values) throws SQLException { public boolean containsDistinct(Value[] values) throws SQLException {
if (!distinct) { if (!distinct) {
throw Message.getInternalError(); throw Message.getInternalError();
...@@ -199,6 +249,11 @@ public class LocalResult implements ResultInterface { ...@@ -199,6 +249,11 @@ public class LocalResult implements ResultInterface {
return rowId; return rowId;
} }
/**
* Add a row to this object.
*
* @param values the row to add
*/
public void addRow(Value[] values) throws SQLException { public void addRow(Value[] values) throws SQLException {
if (distinct) { if (distinct) {
if (distinctRows != null) { if (distinctRows != null) {
...@@ -234,6 +289,9 @@ public class LocalResult implements ResultInterface { ...@@ -234,6 +289,9 @@ public class LocalResult implements ResultInterface {
return visibleColumnCount; return visibleColumnCount;
} }
/**
* This method is called after all rows have been added.
*/
public void done() throws SQLException { public void done() throws SQLException {
if (distinct) { if (distinct) {
if (distinctRows != null) { if (distinctRows != null) {
...@@ -283,6 +341,11 @@ public class LocalResult implements ResultInterface { ...@@ -283,6 +341,11 @@ public class LocalResult implements ResultInterface {
return rowCount; return rowCount;
} }
/**
* Set the number of rows that this result will return at the maximum.
*
* @param limit the limit
*/
public void setLimit(int limit) { public void setLimit(int limit) {
this.limit = limit; this.limit = limit;
} }
...@@ -303,6 +366,11 @@ public class LocalResult implements ResultInterface { ...@@ -303,6 +366,11 @@ public class LocalResult implements ResultInterface {
} }
} }
/**
* Check if this result set is buffered using a temporary file.
*
* @return true if it is
*/
public boolean needToClose() { public boolean needToClose() {
return disk != null; return disk != null;
} }
...@@ -355,6 +423,11 @@ public class LocalResult implements ResultInterface { ...@@ -355,6 +423,11 @@ public class LocalResult implements ResultInterface {
return expressions[i].getScale(); return expressions[i].getScale();
} }
/**
* Set the offset of the first row to return.
*
* @param offset the offset
*/
public void setOffset(int offset) { public void setOffset(int offset) {
this.offset = offset; this.offset = offset;
} }
...@@ -387,6 +460,11 @@ public class LocalResult implements ResultInterface { ...@@ -387,6 +460,11 @@ public class LocalResult implements ResultInterface {
return "columns: " + visibleColumnCount + " rows: " + rowCount + " pos: " + rowId; return "columns: " + visibleColumnCount + " rows: " + rowCount + " pos: " + rowId;
} }
/**
* Check if this result set is closed.
*
* @return true if it is
*/
public boolean isClosed() { public boolean isClosed() {
return closed; return closed;
} }
......
...@@ -25,6 +25,11 @@ public class ResultColumn { ...@@ -25,6 +25,11 @@ public class ResultColumn {
boolean autoIncrement; boolean autoIncrement;
int nullable; int nullable;
/**
* Read an object from the given transfer object.
*
* @param in the object from where to read the data
*/
ResultColumn(Transfer in) throws IOException { ResultColumn(Transfer in) throws IOException {
alias = in.readString(); alias = in.readString();
schemaName = in.readString(); schemaName = in.readString();
...@@ -38,6 +43,13 @@ public class ResultColumn { ...@@ -38,6 +43,13 @@ public class ResultColumn {
nullable = in.readInt(); nullable = in.readInt();
} }
/**
* Write a result column to the given output.
*
* @param out the object to where to write the data
* @param result the result
* @param i the column index
*/
public static void writeColumn(Transfer out, ResultInterface result, int i) throws IOException { public static void writeColumn(Transfer out, ResultInterface result, int i) throws IOException {
out.writeString(result.getAlias(i)); out.writeString(result.getAlias(i));
out.writeString(result.getSchemaName(i)); out.writeString(result.getSchemaName(i));
......
...@@ -17,20 +17,58 @@ import org.h2.value.Value; ...@@ -17,20 +17,58 @@ import org.h2.value.Value;
*/ */
public interface ResultExternal { public interface ResultExternal {
/**
* Reset the current position of this object.
*/
void reset() throws SQLException; void reset() throws SQLException;
/**
* Get the next row from the result.
*
* @return the next row or null
*/
Value[] next() throws SQLException; Value[] next() throws SQLException;
/**
* Add a number of rows to the result.
*
* @param rows the list of rows to add
*/
void addRows(ObjectArray rows) throws SQLException; void addRows(ObjectArray rows) throws SQLException;
/**
* This method is called after all rows have been added.
*/
void done() throws SQLException; void done() throws SQLException;
/**
* Close this object and delete the temporary file.
*/
void close(); void close();
/**
* Remove the row with the given values from this object if such a row
* exists.
*
* @param values the row
* @return the new row count
*/
int removeRow(Value[] values) throws SQLException; int removeRow(Value[] values) throws SQLException;
/**
* Check if the given row exists in this object.
*
* @param values the row
* @return true if it exists
*/
boolean contains(Value[] values) throws SQLException; boolean contains(Value[] values) throws SQLException;
/**
* Add a row to this object.
*
* @param values the row to add
* @return the new number of rows in this object
*/
int addRow(Value[] values) throws SQLException; int addRow(Value[] values) throws SQLException;
} }
...@@ -38,7 +38,11 @@ public class RowList { ...@@ -38,7 +38,11 @@ public class RowList {
private boolean written; private boolean written;
private boolean readUncached; private boolean readUncached;
/**
* Construct a new row list for this session.
*
* @param session the session
*/
public RowList(Session session) { public RowList(Session session) {
this.session = session; this.session = session;
if (SysProperties.DEFAULT_MAX_OPERATION_MEMORY > 0 && session.getDatabase().isPersistent()) { if (SysProperties.DEFAULT_MAX_OPERATION_MEMORY > 0 && session.getDatabase().isPersistent()) {
...@@ -114,6 +118,12 @@ public class RowList { ...@@ -114,6 +118,12 @@ public class RowList {
file.write(buff.getBytes(), 0, buff.length()); file.write(buff.getBytes(), 0, buff.length());
} }
/**
* Add a row to the list.
*
* @param r the row to add
*/
public void add(Row r) throws SQLException { public void add(Row r) throws SQLException {
list.add(r); list.add(r);
memory += r.getMemorySize(); memory += r.getMemorySize();
...@@ -123,6 +133,9 @@ public class RowList { ...@@ -123,6 +133,9 @@ public class RowList {
size++; size++;
} }
/**
* Remove all rows from the list.
*/
public void reset() throws SQLException { public void reset() throws SQLException {
index = 0; index = 0;
if (file != null) { if (file != null) {
...@@ -136,6 +149,11 @@ public class RowList { ...@@ -136,6 +149,11 @@ public class RowList {
} }
} }
/**
* Check if there are more rows in this list.
*
* @return true it there are more rows
*/
public boolean hasNext() { public boolean hasNext() {
return index < size; return index < size;
} }
...@@ -182,6 +200,11 @@ public class RowList { ...@@ -182,6 +200,11 @@ public class RowList {
return row; return row;
} }
/**
* Get the next row from the list.
*
* @return the next row
*/
public Row next() throws SQLException { public Row next() throws SQLException {
Row r; Row r;
if (file == null) { if (file == null) {
...@@ -214,14 +237,25 @@ public class RowList { ...@@ -214,14 +237,25 @@ public class RowList {
return r; return r;
} }
/**
* Get the number of rows in this list.
*
* @return the number of rows
*/
public int size() { public int size() {
return size; return size;
} }
/**
* Do not use the cache.
*/
public void invalidateCache() { public void invalidateCache() {
readUncached = true; readUncached = true;
} }
/**
* Close the result list and delete the temporary file.
*/
public void close() { public void close() {
if (file != null) { if (file != null) {
file.closeAndDeleteSilently(); file.closeAndDeleteSilently();
......
...@@ -20,7 +20,12 @@ import org.h2.table.Table; ...@@ -20,7 +20,12 @@ import org.h2.table.Table;
* CREATE SEQUENCE * CREATE SEQUENCE
*/ */
public class Sequence extends SchemaObjectBase { public class Sequence extends SchemaObjectBase {
/**
* The default cache size for sequences.
*/
public static final int DEFAULT_CACHE_SIZE = 32; public static final int DEFAULT_CACHE_SIZE = 32;
private long value = 1; private long value = 1;
private long valueWithMargin; private long valueWithMargin;
private long increment = 1; private long increment = 1;
...@@ -83,6 +88,12 @@ public class Sequence extends SchemaObjectBase { ...@@ -83,6 +88,12 @@ public class Sequence extends SchemaObjectBase {
return buff.toString(); return buff.toString();
} }
/**
* Get the next value for this sequence.
*
* @param session the session
* @return the next value
*/
public synchronized long getNext(Session session) throws SQLException { public synchronized long getNext(Session session) throws SQLException {
if ((increment > 0 && value >= valueWithMargin) || (increment < 0 && value <= valueWithMargin)) { if ((increment > 0 && value >= valueWithMargin) || (increment < 0 && value <= valueWithMargin)) {
valueWithMargin += increment * cacheSize; valueWithMargin += increment * cacheSize;
...@@ -93,6 +104,11 @@ public class Sequence extends SchemaObjectBase { ...@@ -93,6 +104,11 @@ public class Sequence extends SchemaObjectBase {
return v; return v;
} }
/**
* Flush the current value, including the margin, to disk.
*
* @param session the session
*/
public synchronized void flush(Session session) throws SQLException { public synchronized void flush(Session session) throws SQLException {
Session sysSession = database.getSystemSession(); Session sysSession = database.getSystemSession();
if (session == null || !database.isSysTableLocked()) { if (session == null || !database.isSysTableLocked()) {
...@@ -118,6 +134,9 @@ public class Sequence extends SchemaObjectBase { ...@@ -118,6 +134,9 @@ public class Sequence extends SchemaObjectBase {
} }
} }
/**
* Flush the current value to disk and close this object.
*/
public void close() throws SQLException { public void close() throws SQLException {
valueWithMargin = value; valueWithMargin = value;
flush(null); flush(null);
......
...@@ -28,6 +28,9 @@ import org.h2.value.Value; ...@@ -28,6 +28,9 @@ import org.h2.value.Value;
*/ */
public class TriggerObject extends SchemaObjectBase { public class TriggerObject extends SchemaObjectBase {
/**
* The default queue size.
*/
public static final int DEFAULT_QUEUE_SIZE = 1024; public static final int DEFAULT_QUEUE_SIZE = 1024;
private boolean before; private boolean before;
...@@ -65,6 +68,14 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -65,6 +68,14 @@ public class TriggerObject extends SchemaObjectBase {
} }
} }
/**
* Set the trigger class name and load the class if possible.
*
* @param session the session
* @param triggerClassName the name of the trigger class
* @param force whether exceptions (due to missing class or access rights)
* should be ignored
*/
public void setTriggerClassName(Session session, String triggerClassName, boolean force) throws SQLException { public void setTriggerClassName(Session session, String triggerClassName, boolean force) throws SQLException {
this.triggerClassName = triggerClassName; this.triggerClassName = triggerClassName;
try { try {
...@@ -76,6 +87,14 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -76,6 +87,14 @@ public class TriggerObject extends SchemaObjectBase {
} }
} }
/**
* Call the trigger class if required. This method does nothing if the
* trigger is not defined for the given action. This method is called before
* or after any rows have been processed, once for each statement.
*
* @param session the session
* @param beforeAction if this method is called before applying the changes
*/
public void fire(Session session, boolean beforeAction) throws SQLException { public void fire(Session session, boolean beforeAction) throws SQLException {
if (rowBased || before != beforeAction) { if (rowBased || before != beforeAction) {
return; return;
...@@ -106,7 +125,10 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -106,7 +125,10 @@ public class TriggerObject extends SchemaObjectBase {
} }
/** /**
* Call the fire method of the user-defined trigger class. * Call the fire method of the user-defined trigger class if required. This
* method does nothing if the trigger is not defined for the given action.
* This method is called before or after a row is processed, possibly many
* times for each statement.
* *
* @param session the session * @param session the session
* @param oldRow the old row * @param oldRow the old row
...@@ -172,6 +194,11 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -172,6 +194,11 @@ public class TriggerObject extends SchemaObjectBase {
} }
} }
/**
* Set the trigger type.
*
* @param typeMask the type
*/
public void setTypeMask(int typeMask) { public void setTypeMask(int typeMask) {
this.typeMask = typeMask; this.typeMask = typeMask;
} }
...@@ -267,14 +294,29 @@ public class TriggerObject extends SchemaObjectBase { ...@@ -267,14 +294,29 @@ public class TriggerObject extends SchemaObjectBase {
// nothing to do // nothing to do
} }
/**
* Get the table of this trigger.
*
* @return the table
*/
public Table getTable() { public Table getTable() {
return table; return table;
} }
/**
* Check if this is a before trigger.
*
* @return true if it is
*/
public boolean getBefore() { public boolean getBefore() {
return before; return before;
} }
/**
* Get the trigger class name
*
* @return the class name
*/
public String getTriggerClassName() { public String getTriggerClassName() {
return triggerClassName; return triggerClassName;
} }
......
...@@ -28,6 +28,10 @@ public class AES implements BlockCipher { ...@@ -28,6 +28,10 @@ public class AES implements BlockCipher {
private static final int[] RT3 = new int[256]; private static final int[] RT3 = new int[256];
private int[] encKey = new int[44]; private int[] encKey = new int[44];
private int[] decKey = new int[44]; private int[] decKey = new int[44];
AES() {
// do nothing
}
private static int rot8(int x) { private static int rot8(int x) {
return (x >>> 8) | (x << 24); return (x >>> 8) | (x << 24);
...@@ -117,12 +121,12 @@ public class AES implements BlockCipher { ...@@ -117,12 +121,12 @@ public class AES implements BlockCipher {
decKey[d++] = encKey[e++]; decKey[d++] = encKey[e++];
} }
public void encrypt(byte[] buff, int off, int len) { public void encrypt(byte[] bytes, int off, int len) {
if (SysProperties.CHECK && (len % ALIGN != 0)) { if (SysProperties.CHECK && (len % ALIGN != 0)) {
throw Message.getInternalError("unaligned len " + len); throw Message.getInternalError("unaligned len " + len);
} }
for (int i = off; i < off + len; i += 16) { for (int i = off; i < off + len; i += 16) {
encryptBlock(buff, buff, i); encryptBlock(bytes, bytes, i);
} }
} }
......
...@@ -11,8 +11,8 @@ package org.h2.security; ...@@ -11,8 +11,8 @@ package org.h2.security;
*/ */
public interface BlockCipher { public interface BlockCipher {
/* /**
* Blocks sizes are always multiples of this number * Blocks sizes are always multiples of this number.
*/ */
int ALIGN = 16; int ALIGN = 16;
......
...@@ -16,6 +16,12 @@ import org.h2.message.Message; ...@@ -16,6 +16,12 @@ import org.h2.message.Message;
*/ */
public class CipherFactory { public class CipherFactory {
/**
* Get a new block cipher object for the given algorithm.
*
* @param algorithm the algorithm
* @return a new cipher object
*/
public static BlockCipher getBlockCipher(String algorithm) throws SQLException { public static BlockCipher getBlockCipher(String algorithm) throws SQLException {
if ("XTEA".equalsIgnoreCase(algorithm)) { if ("XTEA".equalsIgnoreCase(algorithm)) {
return new XTEA(); return new XTEA();
...@@ -26,6 +32,12 @@ public class CipherFactory { ...@@ -26,6 +32,12 @@ public class CipherFactory {
} }
} }
/**
* Get a new cryptographic hash object for the given algorithm.
*
* @param algorithm the algorithm
* @return a new hash object
*/
public static SHA256 getHash(String algorithm) throws SQLException { public static SHA256 getHash(String algorithm) throws SQLException {
if ("SHA256".equalsIgnoreCase(algorithm)) { if ("SHA256".equalsIgnoreCase(algorithm)) {
return new SHA256(); return new SHA256();
......
...@@ -15,13 +15,35 @@ public class SHA256 { ...@@ -15,13 +15,35 @@ public class SHA256 {
// TODO maybe implement WHIRLPOOL // TODO maybe implement WHIRLPOOL
/**
* Calculate the hash code by using the given salt. The salt is appended
* after the data before the hash code is calculated. After generating the
* hash code, the data and all internal buffers are nulled out to avoid
* keeping insecure data in memory longer than required (and possibly
* swapped to disk).
*
* @param data the data to hash
* @param salt the salt to use
* @return the hash code
*/
public byte[] getHashWithSalt(byte[] data, byte[] salt) { public byte[] getHashWithSalt(byte[] data, byte[] salt) {
byte[] buff = new byte[data.length + salt.length]; byte[] buff = new byte[data.length + salt.length];
System.arraycopy(data, 0, buff, 0, data.length); System.arraycopy(data, 0, buff, 0, data.length);
System.arraycopy(salt, 0, buff, data.length, salt.length); System.arraycopy(salt, 0, buff, data.length, salt.length);
return getHash(buff); return getHash(buff, true);
} }
/**
* Calculate the hash of a password by prepending the user name and a '@'
* character. Both the user name and the password are encoded to a byte
* array using UTF-16. After generating the hash code, the password array
* and all internal buffers are nulled out to avoid keeping the plain text
* password in memory longer than required (and possibly swapped to disk).
*
* @param userName the user name
* @param the password
* @return the hash code
*/
public byte[] getKeyPasswordHash(String userName, char[] password) { public byte[] getKeyPasswordHash(String userName, char[] password) {
String user = userName + "@"; String user = userName + "@";
byte[] buff = new byte[2 * (user.length() + password.length)]; byte[] buff = new byte[2 * (user.length() + password.length)];
...@@ -37,11 +59,13 @@ public class SHA256 { ...@@ -37,11 +59,13 @@ public class SHA256 {
buff[n++] = (byte) (c); buff[n++] = (byte) (c);
} }
Arrays.fill(password, (char) 0); Arrays.fill(password, (char) 0);
return getHash(buff); return getHash(buff, true);
} }
// The first 32 bits of the fractional parts of the cube roots of the first /**
// sixty-four prime numbers * The first 32 bits of the fractional parts of the cube roots of the first
* sixty-four prime numbers.
*/
private static final int[] K = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, private static final int[] K = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
...@@ -56,12 +80,21 @@ public class SHA256 { ...@@ -56,12 +80,21 @@ public class SHA256 {
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814,
0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/**
public byte[] getHash(byte[] data) { * Calculate the hash code for the given data.
*
* @param data the data to hash
* @param nullData if the data should be nulled after calculating the hash code
* @return the hash code
*/
public byte[] getHash(byte[] data, boolean nullData) {
int byteLen = data.length; int byteLen = data.length;
int intLen = ((byteLen + 9 + 63) / 64) * 16; int intLen = ((byteLen + 9 + 63) / 64) * 16;
byte[] bytes = new byte[intLen * 4]; byte[] bytes = new byte[intLen * 4];
System.arraycopy(data, 0, bytes, 0, byteLen); System.arraycopy(data, 0, bytes, 0, byteLen);
if (nullData) {
Arrays.fill(data, (byte) 0);
}
bytes[byteLen] = (byte) 0x80; bytes[byteLen] = (byte) 0x80;
int[] buff = new int[intLen]; int[] buff = new int[intLen];
for (int i = 0, j = 0; j < intLen; i += 4, j++) { for (int i = 0, j = 0; j < intLen; i += 4, j++) {
...@@ -72,7 +105,6 @@ public class SHA256 { ...@@ -72,7 +105,6 @@ public class SHA256 {
int[] w = new int[64]; int[] w = new int[64];
int[] hh = new int[] { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, int[] hh = new int[] { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
for (int block = 0; block < intLen; block += 16) { for (int block = 0; block < intLen; block += 16) {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
w[i] = buff[block + i]; w[i] = buff[block + i];
......
...@@ -53,10 +53,10 @@ public class SecureFileStore extends FileStore { ...@@ -53,10 +53,10 @@ public class SecureFileStore extends FileStore {
SHA256 sha = new SHA256(); SHA256 sha = new SHA256();
key = sha.getHashWithSalt(key, salt); key = sha.getHashWithSalt(key, salt);
for (int i = 0; i < keyIterations; i++) { for (int i = 0; i < keyIterations; i++) {
key = sha.getHash(key); key = sha.getHash(key, true);
} }
cipher.setKey(key); cipher.setKey(key);
key = sha.getHash(key); key = sha.getHash(key, true);
cipherForInitVector.setKey(key); cipherForInitVector.setKey(key);
} }
......
...@@ -34,7 +34,6 @@ import org.h2.message.Message; ...@@ -34,7 +34,6 @@ import org.h2.message.Message;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.NetUtils;
/** /**
* A factory to create encrypted sockets. To generate new keystore, use the * A factory to create encrypted sockets. To generate new keystore, use the
...@@ -42,26 +41,24 @@ import org.h2.util.NetUtils; ...@@ -42,26 +41,24 @@ import org.h2.util.NetUtils;
*/ */
public class SecureSocketFactory { public class SecureSocketFactory {
/**
* The default password to use for the .h2.keystore file
*/
public static final String KEYSTORE_PASSWORD = "h2pass";
private static final String KEYSTORE = ".h2.keystore"; private static final String KEYSTORE = ".h2.keystore";
private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore"; private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore";
private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword"; private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword";
public static final String KEYSTORE_PASSWORD = "h2pass";
private static SecureSocketFactory factory;
private static final String ANONYMOUS_CIPHER_SUITE = "SSL_DH_anon_WITH_RC4_128_MD5"; private static final String ANONYMOUS_CIPHER_SUITE = "SSL_DH_anon_WITH_RC4_128_MD5";
private static void setFactory(SecureSocketFactory f) { /**
factory = f; * Create a secure client socket that is connected to the given address and port.
} *
* @param address the address to connect to
public static SecureSocketFactory getInstance() { * @param port the port
if (factory == null) { * @return the socket
setFactory(new SecureSocketFactory()); */
} public static Socket createSocket(InetAddress address, int port) throws IOException {
return factory;
}
public Socket createSocket(InetAddress address, int port) throws IOException {
Socket socket = null; Socket socket = null;
//## Java 1.4 begin ## //## Java 1.4 begin ##
setKeystore(); setKeystore();
...@@ -77,13 +74,19 @@ public class SecureSocketFactory { ...@@ -77,13 +74,19 @@ public class SecureSocketFactory {
return socket; return socket;
} }
public ServerSocket createServerSocket(int port) throws IOException { /**
* Create a secure server socket. If a bind address is specified, the socket is only bound to this address.
*
* @param port the port to listen on
* @param bindAddress the address to bind to, or null to bind to all addresses
* @return the server socket
*/
public static ServerSocket createServerSocket(int port, InetAddress bindAddress) throws IOException {
ServerSocket socket = null; ServerSocket socket = null;
//## Java 1.4 begin ## //## Java 1.4 begin ##
setKeystore(); setKeystore();
ServerSocketFactory f = SSLServerSocketFactory.getDefault(); ServerSocketFactory f = SSLServerSocketFactory.getDefault();
SSLServerSocket secureSocket; SSLServerSocket secureSocket;
InetAddress bindAddress = NetUtils.getBindAddress();
if (bindAddress == null) { if (bindAddress == null) {
secureSocket = (SSLServerSocket) f.createServerSocket(port); secureSocket = (SSLServerSocket) f.createServerSocket(port);
} else { } else {
...@@ -113,7 +116,16 @@ public class SecureSocketFactory { ...@@ -113,7 +116,16 @@ public class SecureSocketFactory {
} }
return bout.toByteArray(); return bout.toByteArray();
} }
//## Java 1.4 end ##
/**
* Get the keystore object using the given password.
*
* @param password the keystore password
* @return the keystore
*/
//## Java 1.4 begin ##
public static KeyStore getKeyStore(String password) throws IOException { public static KeyStore getKeyStore(String password) throws IOException {
try { try {
// The following source code can be re-generated // The following source code can be re-generated
...@@ -145,7 +157,7 @@ public class SecureSocketFactory { ...@@ -145,7 +157,7 @@ public class SecureSocketFactory {
} }
} }
private void setKeystore() throws IOException { private static void setKeystore() throws IOException {
Properties p = System.getProperties(); Properties p = System.getProperties();
if (p.getProperty(KEYSTORE_KEY) == null) { if (p.getProperty(KEYSTORE_KEY) == null) {
String fileName = FileUtils.getFileInUserHome(KEYSTORE); String fileName = FileUtils.getFileInUserHome(KEYSTORE);
...@@ -176,7 +188,7 @@ public class SecureSocketFactory { ...@@ -176,7 +188,7 @@ public class SecureSocketFactory {
} }
} }
private String[] addAnonymous(String[] list) { private static String[] addAnonymous(String[] list) {
String[] newList = new String[list.length + 1]; String[] newList = new String[list.length + 1];
System.arraycopy(list, 0, newList, 1, list.length); System.arraycopy(list, 0, newList, 1, list.length);
newList[0] = ANONYMOUS_CIPHER_SUITE; newList[0] = ANONYMOUS_CIPHER_SUITE;
......
...@@ -21,6 +21,10 @@ public class XTEA implements BlockCipher { ...@@ -21,6 +21,10 @@ public class XTEA implements BlockCipher {
private static final int DELTA = 0x9E3779B9; private static final int DELTA = 0x9E3779B9;
private int k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15; private int k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15;
private int k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31; private int k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31;
XTEA() {
// do nothing
}
public void setKey(byte[] b) { public void setKey(byte[] b) {
int[] key = new int[4]; int[] key = new int[4];
...@@ -57,7 +61,7 @@ public class XTEA implements BlockCipher { ...@@ -57,7 +61,7 @@ public class XTEA implements BlockCipher {
} }
} }
public void encryptBlock(byte[] in, byte[] out, int off) { private void encryptBlock(byte[] in, byte[] out, int off) {
int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255); int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255);
int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255); int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255);
y += (((z << 4) ^ (z >>> 5)) + z) ^ k0; z += (((y >>> 5) ^ (y << 4)) + y) ^ k1; y += (((z << 4) ^ (z >>> 5)) + z) ^ k0; z += (((y >>> 5) ^ (y << 4)) + y) ^ k1;
...@@ -80,7 +84,7 @@ public class XTEA implements BlockCipher { ...@@ -80,7 +84,7 @@ public class XTEA implements BlockCipher {
out[off+4] = (byte) (z >> 24); out[off+5] = (byte) (z >> 16); out[off+6] = (byte) (z >> 8); out[off+7] = (byte) z; out[off+4] = (byte) (z >> 24); out[off+5] = (byte) (z >> 16); out[off+6] = (byte) (z >> 8); out[off+7] = (byte) z;
} }
public void decryptBlock(byte[] in, byte[] out, int off) { private void decryptBlock(byte[] in, byte[] out, int off) {
int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255); int y = (in[off] << 24) | ((in[off+1] & 255) << 16) | ((in[off+2] & 255) << 8) | (in[off+3] & 255);
int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255); int z = (in[off+4] << 24) | ((in[off+5] & 255) << 16) | ((in[off+6] & 255) << 8) | (in[off+7] & 255);
z -= (((y >>> 5) ^ (y << 4)) + y) ^ k31; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k30; z -= (((y >>> 5) ^ (y << 4)) + y) ^ k31; y -= (((z << 4) ^ (z >>> 5)) + z) ^ k30;
......
...@@ -26,6 +26,13 @@ public class NetUtils { ...@@ -26,6 +26,13 @@ public class NetUtils {
private static InetAddress bindAddress; private static InetAddress bindAddress;
/**
* Create a loopback socket (a socket that is connected to localhost) on this port.
*
* @param port the port
* @param ssl if SSL should be used
* @return the socket
*/
public static Socket createLoopbackSocket(int port, boolean ssl) throws IOException { public static Socket createLoopbackSocket(int port, boolean ssl) throws IOException {
InetAddress address = getBindAddress(); InetAddress address = getBindAddress();
if (address == null) { if (address == null) {
...@@ -34,6 +41,14 @@ public class NetUtils { ...@@ -34,6 +41,14 @@ public class NetUtils {
return createSocket(address.getHostAddress(), port, ssl); return createSocket(address.getHostAddress(), port, ssl);
} }
/**
* Create a client socket that is connected to the given address and port.
*
* @param server to connect to (including an optional port)
* @param defaultPort the default port (if not specified in the server address)
* @param ssl if SSL should be used
* @return the socket
*/
public static Socket createSocket(String server, int defaultPort, boolean ssl) throws IOException { public static Socket createSocket(String server, int defaultPort, boolean ssl) throws IOException {
int port = defaultPort; int port = defaultPort;
// IPv6: RFC 2732 format is '[a:b:c:d:e:f:g:h]' or // IPv6: RFC 2732 format is '[a:b:c:d:e:f:g:h]' or
...@@ -50,14 +65,29 @@ public class NetUtils { ...@@ -50,14 +65,29 @@ public class NetUtils {
return createSocket(address, port, ssl); return createSocket(address, port, ssl);
} }
/**
* Create a client socket that is connected to the given address and port.
*
* @param address the address to connect to
* @param port the port
* @param ssl if SSL should be used
* @return the socket
*/
public static Socket createSocket(InetAddress address, int port, boolean ssl) throws IOException { public static Socket createSocket(InetAddress address, int port, boolean ssl) throws IOException {
if (ssl) { if (ssl) {
SecureSocketFactory f = SecureSocketFactory.getInstance(); return SecureSocketFactory.createSocket(address, port);
return f.createSocket(address, port);
} }
return new Socket(address, port); return new Socket(address, port);
} }
/**
* Create a server socket. The system property h2.bindAddress is used if
* set.
*
* @param port the port to listen on
* @param ssl if SSL should be used
* @return the server socket
*/
public static ServerSocket createServerSocket(int port, boolean ssl) throws SQLException { public static ServerSocket createServerSocket(int port, boolean ssl) throws SQLException {
try { try {
return createServerSocketTry(port, ssl); return createServerSocketTry(port, ssl);
...@@ -73,7 +103,7 @@ public class NetUtils { ...@@ -73,7 +103,7 @@ public class NetUtils {
* *
* @return the bind address * @return the bind address
*/ */
public static InetAddress getBindAddress() throws UnknownHostException { private static InetAddress getBindAddress() throws UnknownHostException {
String host = SysProperties.BIND_ADDRESS; String host = SysProperties.BIND_ADDRESS;
if (host == null || host.length() == 0) { if (host == null || host.length() == 0) {
return null; return null;
...@@ -88,11 +118,10 @@ public class NetUtils { ...@@ -88,11 +118,10 @@ public class NetUtils {
private static ServerSocket createServerSocketTry(int port, boolean ssl) throws SQLException { private static ServerSocket createServerSocketTry(int port, boolean ssl) throws SQLException {
try { try {
InetAddress bindAddress = getBindAddress();
if (ssl) { if (ssl) {
SecureSocketFactory f = SecureSocketFactory.getInstance(); return SecureSocketFactory.createServerSocket(port, bindAddress);
return f.createServerSocket(port);
} }
InetAddress bindAddress = getBindAddress();
if (bindAddress == null) { if (bindAddress == null) {
return new ServerSocket(port); return new ServerSocket(port);
} }
...@@ -105,6 +134,12 @@ public class NetUtils { ...@@ -105,6 +134,12 @@ public class NetUtils {
} }
} }
/**
* Check if a socket is connected to localhost.
*
* @param socket the socket
* @return true if it is
*/
public static boolean isLoopbackAddress(Socket socket) { public static boolean isLoopbackAddress(Socket socket) {
boolean result = true; boolean result = true;
//## Java 1.4 begin ## //## Java 1.4 begin ##
...@@ -113,6 +148,12 @@ public class NetUtils { ...@@ -113,6 +148,12 @@ public class NetUtils {
return result; return result;
} }
/**
* Close a server socket and ignore any exceptions.
*
* @param socket the socket
* @return null
*/
public static ServerSocket closeSilently(ServerSocket socket) { public static ServerSocket closeSilently(ServerSocket socket) {
if (socket != null) { if (socket != null) {
try { try {
...@@ -124,6 +165,11 @@ public class NetUtils { ...@@ -124,6 +165,11 @@ public class NetUtils {
return null; return null;
} }
/**
* Get the local host address as a string.
*
* @return the local host address
*/
public static String getLocalAddress() { public static String getLocalAddress() {
InetAddress bind = null; InetAddress bind = null;
try { try {
......
...@@ -160,12 +160,13 @@ java org.h2.test.TestAll timer ...@@ -160,12 +160,13 @@ java org.h2.test.TestAll timer
/* /*
http://patir.rubyforge.org/rutema/index.html
Rutema is a test execution and management tool for heterogeneous development environments written in Ruby.
jazoon jazoon
upload and test javadoc/index.html upload and test javadoc/index.html
download PostgreSQL docs
in help.csv, use complete examples for functions; add a test case in help.csv, use complete examples for functions; add a test case
improve javadocs improve javadocs
...@@ -233,6 +234,9 @@ Roadmap: ...@@ -233,6 +234,9 @@ Roadmap:
sometimes a stack overflow exception was thrown instead of a IO exception. sometimes a stack overflow exception was thrown instead of a IO exception.
The H2 Console could not be shut down from within the tool if the The H2 Console could not be shut down from within the tool if the
browser supports keepAlive (most browsers do). browser supports keepAlive (most browsers do).
If the password was passed as a char array, it was kept in an internal buffer
longer than required. Theoretically the password could have been stolen
if the main memory was swapped to disk before the garbage collection was run.
*/ */
if (args.length > 0) { if (args.length > 0) {
......
--- special grammar and test cases --------------------------------------------------------------------------------------------- --- special grammar and test cases ---------------------------------------------------------------------------------------------
alter table information_schema.help rename to information_schema.help2;
> exception
help abc;
> ID SECTION TOPIC SYNTAX TEXT EXAMPLE
> -- ------- ----- ------ ---- -------
> rows: 0
CREATE TABLE test (id int(25) NOT NULL auto_increment, name varchar NOT NULL, PRIMARY KEY (id,name)); CREATE TABLE test (id int(25) NOT NULL auto_increment, name varchar NOT NULL, PRIMARY KEY (id,name));
> ok > ok
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import org.h2.security.AES; import org.h2.security.BlockCipher;
import org.h2.security.CipherFactory;
import org.h2.security.SHA256; import org.h2.security.SHA256;
import org.h2.security.XTEA;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
...@@ -28,8 +28,11 @@ public class TestSecurity extends TestBase { ...@@ -28,8 +28,11 @@ public class TestSecurity extends TestBase {
testOneSHA(sha); testOneSHA(sha);
} }
private String getHashString(SHA256 sha, byte[] data) { private String getHashString(SHA256 sha, byte[] data) throws Exception {
byte[] result = sha.getHash(data); byte[] result = sha.getHash(data, true);
if (data.length > 0) {
check(data[0], 0);
}
return ByteUtils.convertBytesToString(result); return ByteUtils.convertBytesToString(result);
} }
...@@ -63,21 +66,21 @@ public class TestSecurity extends TestBase { ...@@ -63,21 +66,21 @@ public class TestSecurity extends TestBase {
void checkSHA256(String message, String expected) throws Exception { void checkSHA256(String message, String expected) throws Exception {
SHA256 sha = new SHA256(); SHA256 sha = new SHA256();
String hash = ByteUtils.convertBytesToString(sha.getHash(message.getBytes())).toUpperCase(); String hash = ByteUtils.convertBytesToString(sha.getHash(message.getBytes(), true)).toUpperCase();
check(expected, hash); check(expected, hash);
} }
public void testXTEA() throws Exception { public void testXTEA() throws Exception {
byte[] test = new byte[4096]; byte[] test = new byte[4096];
XTEA xtea = new XTEA(); BlockCipher xtea = CipherFactory.getBlockCipher("XTEA");
xtea.setKey("abcdefghijklmnop".getBytes()); xtea.setKey("abcdefghijklmnop".getBytes());
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
xtea.decryptBlock(test, test, 0); xtea.decrypt(test, 0, test.length);
} }
} }
private void testAES() throws Exception { private void testAES() throws Exception {
AES test = new AES(); BlockCipher test = CipherFactory.getBlockCipher("AES");
test.setKey(ByteUtils.convertStringToBytes("000102030405060708090A0B0C0D0E0F")); test.setKey(ByteUtils.convertStringToBytes("000102030405060708090A0B0C0D0E0F"));
byte[] in = new byte[128]; byte[] in = new byte[128];
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论