Skip to content

Commit a235a2b

Browse files
committed
SQL: new .hash() method. Fixed issue orientechnologies#2353
1 parent 6e95ad4 commit a235a2b

File tree

4 files changed

+132
-43
lines changed

4 files changed

+132
-43
lines changed

core/src/main/java/com/orientechnologies/orient/core/security/OSecurityManager.java

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,19 @@
1515
*/
1616
package com.orientechnologies.orient.core.security;
1717

18-
import java.io.UnsupportedEncodingException;
19-
import java.security.Key;
20-
import java.security.MessageDigest;
21-
import java.security.NoSuchAlgorithmException;
18+
import com.orientechnologies.common.log.OLogManager;
19+
import com.orientechnologies.orient.core.exception.OConfigurationException;
20+
import com.orientechnologies.orient.core.exception.OSecurityAccessException;
21+
import com.orientechnologies.orient.core.exception.OSecurityException;
2222

2323
import javax.crypto.Cipher;
2424
import javax.crypto.KeyGenerator;
2525
import javax.crypto.SecretKey;
2626
import javax.crypto.spec.SecretKeySpec;
27-
28-
import com.orientechnologies.common.log.OLogManager;
29-
import com.orientechnologies.orient.core.exception.OConfigurationException;
30-
import com.orientechnologies.orient.core.exception.OSecurityAccessException;
31-
import com.orientechnologies.orient.core.exception.OSecurityException;
27+
import java.io.UnsupportedEncodingException;
28+
import java.security.Key;
29+
import java.security.MessageDigest;
30+
import java.security.NoSuchAlgorithmException;
3231

3332
public class OSecurityManager {
3433

@@ -47,6 +46,35 @@ public OSecurityManager() {
4746
}
4847
}
4948

49+
public static String digest2String(final String iInput, String iAlgorithm) throws NoSuchAlgorithmException,
50+
UnsupportedEncodingException {
51+
if (iAlgorithm == null)
52+
iAlgorithm = ALGORITHM;
53+
54+
final MessageDigest msgDigest = MessageDigest.getInstance(iAlgorithm);
55+
56+
return byteArrayToHexStr(msgDigest.digest(iInput.getBytes("UTF-8")));
57+
}
58+
59+
public static OSecurityManager instance() {
60+
return instance;
61+
}
62+
63+
private static String byteArrayToHexStr(final byte[] data) {
64+
if (data == null)
65+
return null;
66+
67+
final char[] chars = new char[data.length * 2];
68+
for (int i = 0; i < data.length; i++) {
69+
final byte current = data[i];
70+
final int hi = (current & 0xF0) >> 4;
71+
final int lo = current & 0x0F;
72+
chars[2 * i] = (char) (hi < 10 ? ('0' + hi) : ('A' + hi - 10));
73+
chars[2 * i + 1] = (char) (lo < 10 ? ('0' + lo) : ('A' + lo - 10));
74+
}
75+
return new String(chars);
76+
}
77+
5078
public boolean check(final byte[] iInput1, final byte[] iInput2) {
5179
return MessageDigest.isEqual(iInput1, iInput2);
5280
}
@@ -140,23 +168,4 @@ public byte[] decrypt(final String iAlgorithm, final Key iKey, final byte[] iDat
140168
throw new OSecurityException("Error on decrypting data", e);
141169
}
142170
}
143-
144-
public static OSecurityManager instance() {
145-
return instance;
146-
}
147-
148-
private static String byteArrayToHexStr(final byte[] data) {
149-
if (data == null)
150-
return null;
151-
152-
final char[] chars = new char[data.length * 2];
153-
for (int i = 0; i < data.length; i++) {
154-
final byte current = data[i];
155-
final int hi = (current & 0xF0) >> 4;
156-
final int lo = current & 0x0F;
157-
chars[2 * i] = (char) (hi < 10 ? ('0' + hi) : ('A' + hi - 10));
158-
chars[2 * i + 1] = (char) (lo < 10 ? ('0' + lo) : ('A' + lo - 10));
159-
}
160-
return new String(chars);
161-
}
162171
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2013 Orient Technologies.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.orientechnologies.orient.core.sql.functions.text;
17+
18+
import com.orientechnologies.orient.core.command.OCommandContext;
19+
import com.orientechnologies.orient.core.db.record.OIdentifiable;
20+
import com.orientechnologies.orient.core.exception.OCommandExecutionException;
21+
import com.orientechnologies.orient.core.security.OSecurityManager;
22+
import com.orientechnologies.orient.core.sql.method.misc.OAbstractSQLMethod;
23+
24+
import java.io.UnsupportedEncodingException;
25+
import java.security.NoSuchAlgorithmException;
26+
27+
/**
28+
* Hash a string supporting multiple algorithm, all those supported by JVM
29+
*
30+
* @author Luca Garulli (l.garulli--at--orientechnologies.com)
31+
*/
32+
public class OSQLMethodHash extends OAbstractSQLMethod {
33+
34+
public static final String NAME = "hash";
35+
36+
public OSQLMethodHash() {
37+
super(NAME, 0, 1);
38+
}
39+
40+
@Override
41+
public String getSyntax() {
42+
return "hash([<algorithm>])";
43+
}
44+
45+
@Override
46+
public Object execute(final Object iThis, final OIdentifiable iCurrentRecord, final OCommandContext iContext,
47+
final Object ioResult, final Object[] iParams) {
48+
if (iThis == null)
49+
return null;
50+
51+
final String algorithm = iParams.length > 0 ? iParams[0].toString() : OSecurityManager.ALGORITHM;
52+
try {
53+
return OSecurityManager.digest2String(iThis.toString(), algorithm);
54+
55+
} catch (NoSuchAlgorithmException e) {
56+
throw new OCommandExecutionException("hash(): algorithm '" + algorithm + "' is not supported");
57+
} catch (UnsupportedEncodingException e) {
58+
throw new OCommandExecutionException("hash(): encoding 'UTF-8' is not supported");
59+
}
60+
}
61+
}

core/src/main/java/com/orientechnologies/orient/core/sql/method/ODefaultSQLMethodFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.orientechnologies.orient.core.sql.functions.misc.OSQLMethodExclude;
2525
import com.orientechnologies.orient.core.sql.functions.misc.OSQLMethodInclude;
2626
import com.orientechnologies.orient.core.sql.functions.text.OSQLMethodAppend;
27+
import com.orientechnologies.orient.core.sql.functions.text.OSQLMethodHash;
2728
import com.orientechnologies.orient.core.sql.functions.text.OSQLMethodLength;
2829
import com.orientechnologies.orient.core.sql.functions.text.OSQLMethodReplace;
2930
import com.orientechnologies.orient.core.sql.functions.text.OSQLMethodRight;
@@ -63,6 +64,7 @@ public ODefaultSQLMethodFactory() {
6364
register(OSQLMethodField.NAME, new OSQLMethodField());
6465
register(OSQLMethodFormat.NAME, new OSQLMethodFormat());
6566
register(OSQLMethodFunctionDelegate.NAME, OSQLMethodFunctionDelegate.class);
67+
register(OSQLMethodHash.NAME, new OSQLMethodHash());
6668
register(OSQLMethodInclude.NAME, new OSQLMethodInclude());
6769
register(OSQLMethodIndexOf.NAME, new OSQLMethodIndexOf());
6870
register(OSQLMethodJavaType.NAME, new OSQLMethodJavaType());

tests/src/test/java/com/orientechnologies/orient/test/database/auto/SQLFunctionsTest.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,34 @@
1515
*/
1616
package com.orientechnologies.orient.test.database.auto;
1717

18-
import java.text.SimpleDateFormat;
19-
import java.util.Collection;
20-
import java.util.Date;
21-
import java.util.HashSet;
22-
import java.util.List;
23-
import java.util.Map;
24-
import java.util.Set;
25-
26-
import org.testng.Assert;
27-
import org.testng.annotations.AfterTest;
28-
import org.testng.annotations.BeforeTest;
29-
import org.testng.annotations.Parameters;
30-
import org.testng.annotations.Test;
31-
3218
import com.orientechnologies.orient.core.command.OCommandContext;
3319
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
3420
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
3521
import com.orientechnologies.orient.core.db.record.OIdentifiable;
3622
import com.orientechnologies.orient.core.metadata.schema.OClass;
3723
import com.orientechnologies.orient.core.metadata.schema.OType;
3824
import com.orientechnologies.orient.core.record.impl.ODocument;
25+
import com.orientechnologies.orient.core.security.OSecurityManager;
3926
import com.orientechnologies.orient.core.sql.OCommandSQL;
4027
import com.orientechnologies.orient.core.sql.OCommandSQLParsingException;
4128
import com.orientechnologies.orient.core.sql.OSQLEngine;
4229
import com.orientechnologies.orient.core.sql.functions.OSQLFunctionAbstract;
4330
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
31+
import org.testng.Assert;
32+
import org.testng.annotations.AfterTest;
33+
import org.testng.annotations.BeforeTest;
34+
import org.testng.annotations.Parameters;
35+
import org.testng.annotations.Test;
36+
37+
import java.io.UnsupportedEncodingException;
38+
import java.security.NoSuchAlgorithmException;
39+
import java.text.SimpleDateFormat;
40+
import java.util.Collection;
41+
import java.util.Date;
42+
import java.util.HashSet;
43+
import java.util.List;
44+
import java.util.Map;
45+
import java.util.Set;
4446

4547
@Test(groups = "sql-select")
4648
public class SQLFunctionsTest {
@@ -336,7 +338,8 @@ public String getSyntax() {
336338
}
337339

338340
@Override
339-
public Object execute(Object iThis, OIdentifiable iCurrentRecord, Object iCurrentResult, final Object[] iParams, OCommandContext iContext) {
341+
public Object execute(Object iThis, OIdentifiable iCurrentRecord, Object iCurrentResult, final Object[] iParams,
342+
OCommandContext iContext) {
340343
if (iParams[0] == null || iParams[1] == null)
341344
// CHECK BOTH EXPECTED PARAMETERS
342345
return null;
@@ -379,6 +382,20 @@ public void queryAsLong() {
379382
}
380383
}
381384

385+
@Test
386+
public void testHashMethod() throws UnsupportedEncodingException, NoSuchAlgorithmException {
387+
List<ODocument> result = database.command(
388+
new OSQLSynchQuery<ODocument>("select name, name.hash() as n256, name.hash('sha-512') as n512 from OUser")).execute();
389+
390+
Assert.assertFalse(result.isEmpty());
391+
for (ODocument d : result) {
392+
final String name = d.field("name");
393+
394+
Assert.assertEquals(OSecurityManager.digest2String(name, "SHA-256"), d.field("n256"));
395+
Assert.assertEquals(OSecurityManager.digest2String(name, "SHA-512"), d.field("n512"));
396+
}
397+
}
398+
382399
@BeforeTest
383400
public void openDatabase() {
384401
database.open("admin", "admin");

0 commit comments

Comments
 (0)