Skip to content

Commit

Permalink
Removed the old AES tool, started writing a new one from scratch.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmihajlovski committed Dec 7, 2016
1 parent 462152c commit 0d3420a
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 143 deletions.
131 changes: 0 additions & 131 deletions rapidoid-commons/src/main/java/org/netnix/AES.java

This file was deleted.

41 changes: 41 additions & 0 deletions rapidoid-commons/src/main/java/org/rapidoid/crypto/AES.java
@@ -0,0 +1,41 @@
package org.rapidoid.crypto;

/*
* #%L
* rapidoid-commons
* %%
* Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;

@Authors("Nikolche Mihajlovski")
@Since("5.3.0")
public class AES extends RapidoidThing {

private static final AESCypherTool INSTANCE = new AESCypherTool();

public static byte[] encrypt(byte[] data, byte[] secret) throws Exception {
return INSTANCE.encrypt(data, secret);
}

public static byte[] decrypt(byte[] data, byte[] secret) throws Exception {
return INSTANCE.decrypt(data, secret);
}

}
@@ -0,0 +1,39 @@
package org.rapidoid.crypto;

/*
* #%L
* rapidoid-commons
* %%
* Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;

@Authors("Nikolche Mihajlovski")
@Since("5.3.0")
public class AESCypherTool extends RapidoidThing {

public byte[] encrypt(byte[] data, byte[] secret) throws Exception {
return null; // FIXME implement this
}

public byte[] decrypt(byte[] data, byte[] secret) throws Exception {
return null; // FIXME implement this
}

}
19 changes: 9 additions & 10 deletions rapidoid-commons/src/main/java/org/rapidoid/crypto/Crypto.java
@@ -1,6 +1,5 @@
package org.rapidoid.crypto;

import org.netnix.AES;
import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
Expand Down Expand Up @@ -140,10 +139,10 @@ private static synchronized void initSecret() {

byte[] rnd = new byte[128];
RANDOM.nextBytes(rnd);
secretKey = Crypto.pbkdf2(Str.toHex(rnd));
secretKey = pbkdf2(Str.toHex(rnd).toCharArray());

} else {
secretKey = Crypto.pbkdf2(secret);
secretKey = pbkdf2(secret.toCharArray());
}
}

Expand Down Expand Up @@ -181,27 +180,27 @@ public static byte[] decrypt(byte[] data) {
return decrypt(data, getSecretKey());
}

public static byte[] pbkdf2(String password, byte[] salt, int iterations, int length) {
public static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int length) {
try {
return AES.generateKey(password, salt, iterations, length);
return CryptoUtil.pbkdf2(password, salt, iterations, length);
} catch (Exception e) {
throw U.rte(e);
}
}

public static byte[] pbkdf2(String password) {
public static byte[] pbkdf2(char[] password) {
return pbkdf2(password, DEFAULT_PBKDF2_SALT, 100000, 256);
}

public static String passwordHash(String password) {
public static String passwordHash(char[] password) {
return passwordHash(password, 100000);
}

public static String passwordHash(String password, int iterations) {
public static String passwordHash(char[] password, int iterations) {
return passwordHash(password, iterations, randomSalt());
}

public static String passwordHash(String password, int iterations, byte[] salt) {
public static String passwordHash(char[] password, int iterations, byte[] salt) {
byte[] hash = pbkdf2(password, salt, iterations, 256);
return Str.toBase64(hash) + "$" + Str.toBase64(salt) + "$" + iterations;
}
Expand All @@ -223,7 +222,7 @@ public static boolean passwordMatches(String password, String saltedHash) {
return false;
}

byte[] realHash = pbkdf2(password, salt, iterations, 256);
byte[] realHash = pbkdf2(password.toCharArray(), salt, iterations, 256);
return Arrays.equals(expectedHash, realHash);
}

Expand Down
80 changes: 80 additions & 0 deletions rapidoid-commons/src/main/java/org/rapidoid/crypto/CryptoUtil.java
@@ -0,0 +1,80 @@
package org.rapidoid.crypto;

/*
* #%L
* rapidoid-commons
* %%
* Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import keywhiz.hkdf.Hkdf;
import org.rapidoid.RapidoidThing;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.u.U;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

@Authors("Nikolche Mihajlovski")
@Since("5.3.0")
public class CryptoUtil extends RapidoidThing {

private static final Hkdf HKDF = Hkdf.usingDefaults();

private static final String HMAC_SHA_256 = "HmacSHA256";

private static final String AES_CTR_NO_PADDING = "AES/CTR/NoPadding";

public static final int AES_KEY_LENGTH = calcAESKeyLength();

private static int calcAESKeyLength() {
int maxKeyLen;
try {
maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
} catch (NoSuchAlgorithmException e) {
throw U.rte(e);
}

return maxKeyLen > 256 ? 256 : 128;
}

public static byte[] hkdf(byte[] secret, byte[] salt, int bitLength) {
SecretKeySpec key = new SecretKeySpec(secret, HMAC_SHA_256);
return HKDF.expand(key, salt, bitLength / 8);
}

public static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int length)
throws NoSuchAlgorithmException, InvalidKeySpecException {

PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, length);

return getPBKDFInstance().generateSecret(keySpec).getEncoded();
}

private static SecretKeyFactory getPBKDFInstance() throws NoSuchAlgorithmException {
try {
return SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
} catch (NoSuchAlgorithmException e) {
return SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
}
}

}
3 changes: 3 additions & 0 deletions rapidoid-commons/src/main/resources/rapidoid-classes.txt
Expand Up @@ -134,7 +134,10 @@ org.rapidoid.config.ConfigParser
org.rapidoid.config.ConfigUtil
org.rapidoid.config.ConfigValueStore
org.rapidoid.config.RapidoidInitializer
org.rapidoid.crypto.AES
org.rapidoid.crypto.AESCypherTool
org.rapidoid.crypto.Crypto
org.rapidoid.crypto.CryptoUtil
org.rapidoid.ctx.Classes
org.rapidoid.ctx.Contextual
org.rapidoid.ctx.Ctx
Expand Down
Expand Up @@ -94,7 +94,7 @@ public void testEncryptWithAppSecret() {

@Test
public void testEncryptWithCustomPassword() {
byte[] key = Crypto.pbkdf2("pass");
byte[] key = Crypto.pbkdf2("pass".toCharArray());

for (int i = 0; i < 10000; i++) {
String msg1 = "" + i;
Expand All @@ -111,7 +111,7 @@ public void testEncryptWithCustomPassword() {
public void testPasswordHash() {
for (int i = 0; i < 10; i++) {
String pass = "" + i;
String hash = Crypto.passwordHash(pass);
String hash = Crypto.passwordHash(pass.toCharArray());

isTrue(Crypto.passwordMatches(pass, hash));
isFalse(Crypto.passwordMatches(pass + "?", hash));
Expand Down

0 comments on commit 0d3420a

Please sign in to comment.