Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .gradle/7.2/executionHistory/executionHistory.bin
Binary file not shown.
Binary file modified .gradle/7.2/executionHistory/executionHistory.lock
Binary file not shown.
Binary file modified .gradle/7.2/fileHashes/fileHashes.bin
Binary file not shown.
Binary file modified .gradle/7.2/fileHashes/fileHashes.lock
Binary file not shown.
Binary file modified .gradle/7.2/fileHashes/resourceHashesCache.bin
Binary file not shown.
Binary file modified .gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
Binary file modified .gradle/buildOutputCleanup/outputFiles.bin
Binary file not shown.
Binary file modified .gradle/checksums/checksums.lock
Binary file not shown.
Binary file modified .gradle/checksums/md5-checksums.bin
Binary file not shown.
Binary file modified .gradle/checksums/sha1-checksums.bin
Binary file not shown.
Binary file modified .gradle/checksums/sha256-checksums.bin
Binary file not shown.
Binary file modified .gradle/checksums/sha512-checksums.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = 'dev.netcode'
version = '0.0.3'
version = '0.0.4'

java {
toolchain {
Expand All @@ -21,7 +21,7 @@ publishing {
from components.java
groupId = 'dev.netcode'
artifactId = 'security'
version = '0.0.3'
version = '0.0.4'
pom {
name = 'netcodes Java security Utilities'
description = 'Security utilities including encryption'
Expand Down
15 changes: 8 additions & 7 deletions src/main/java/dev/netcode/security/encryption/AESEncrypter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.netcode.security.encryption;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
Expand All @@ -26,15 +26,16 @@ public class AESEncrypter {
public static SecretKeySpec getKey(String password) {
MessageDigest sha = null;
SecretKeySpec privateKey = null;
byte[] key = password.getBytes(StandardCharsets.UTF_8);
try {
byte[] key = password.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-256");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
privateKey = new SecretKeySpec(key, "AES");
} catch(NoSuchAlgorithmException | UnsupportedEncodingException e) {
} catch (NoSuchAlgorithmException e) {
// SHA-256 exists so this should never be thrown
e.printStackTrace();
}
}
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
privateKey = new SecretKeySpec(key, "AES");
return privateKey;
}

Expand Down
13 changes: 9 additions & 4 deletions src/main/java/dev/netcode/security/encryption/KeyLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.nio.file.Path;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

import dev.netcode.util.Result;
Expand All @@ -19,8 +20,9 @@ public class KeyLoader {
* @param file Path of the file containing the Base64 encoded public key
* @return the public key
* @throws IOException if the file can not be read
* @throws InvalidKeySpecException in case the loaded key is malformed or currupted
*/
public static PublicKey loadPublicKeyFromFile(Path file) throws IOException {
public static PublicKey loadPublicKeyFromFile(Path file) throws IOException, InvalidKeySpecException {
String publicContent = new String(Files.readAllBytes(file));
publicContent = publicContent.replace("\n", "").replace("\r", "");
publicContent = publicContent.substring(26,publicContent.length()-24);
Expand All @@ -33,8 +35,9 @@ public static PublicKey loadPublicKeyFromFile(Path file) throws IOException {
* @param file Path of the file containing the Base64 encoded private key
* @return the private key
* @throws IOException if the file can not be read
* @throws InvalidKeySpecException in case the loaded key is malformed or currupted
*/
public static PrivateKey loadPrivateKeyFromFile(Path file) throws IOException {
public static PrivateKey loadPrivateKeyFromFile(Path file) throws IOException, InvalidKeySpecException {
String privateContent = new String(Files.readAllBytes(file));
privateContent = privateContent.replace("\n", "").replace("\r", "");
privateContent = privateContent.substring(27,privateContent.length()-25);
Expand All @@ -48,8 +51,9 @@ public static PrivateKey loadPrivateKeyFromFile(Path file) throws IOException {
* @param password used to decrypt the file
* @return the public key
* @throws IOException if the file can not be read
* @throws InvalidKeySpecException in case the loaded key is malformed or currupted
*/
public static Result<PublicKey> loadPublicKeyFromEncryptedFile(Path file, String password) throws IOException {
public static Result<PublicKey> loadPublicKeyFromEncryptedFile(Path file, String password) throws IOException, InvalidKeySpecException {
String publicContent = new String(Files.readAllBytes(file));
var result = AESEncrypter.decrypt(publicContent, password);
if(!result.wasSuccessful()) {
Expand All @@ -66,8 +70,9 @@ public static Result<PublicKey> loadPublicKeyFromEncryptedFile(Path file, String
* @param password used to decrypt the file
* @return the private key
* @throws IOException if the file can not be read
* @throws InvalidKeySpecException in case the loaded key is malformed or currupted
*/
public static Result<PrivateKey> loadPrivateKeyFromEncryptedFile(Path file, String password) throws IOException {
public static Result<PrivateKey> loadPrivateKeyFromEncryptedFile(Path file, String password) throws IOException, InvalidKeySpecException {
String privateContent = new String(Files.readAllBytes(file));
var result = AESEncrypter.decrypt(privateContent, password);
if(!result.wasSuccessful()) {
Expand Down
104 changes: 59 additions & 45 deletions src/main/java/dev/netcode/security/encryption/RSAEncrypter.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
Expand All @@ -12,13 +13,16 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
* This class simplifies the process of RSA Encrypting data.
Expand Down Expand Up @@ -49,18 +53,21 @@ public static KeyPair generateKeyPair(int size) {
* @param cipher data to be decrypted
* @param privateKey to be used to decrypt the data
* @return decrypted data as UTF-8 encoded String
* @throws InvalidKeyException in case the key format is not supported
* @throws BadPaddingException in case something failed while padding
* @throws IllegalBlockSizeException in case the blocksize is invalid
*/
public static String decrypt(byte[] cipher, PrivateKey privateKey) {
public static String decrypt(byte[] cipher, PrivateKey privateKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
byte[] dec = {};
Cipher c;
Cipher c = null;
try {
c = Cipher.getInstance("RSA");
c.init(Cipher.DECRYPT_MODE, privateKey);
dec = c.doFinal(cipher);
} catch(Exception e) {
System.out.println("Error while decrypting: " + e.getMessage());
} catch (NoSuchAlgorithmException |NoSuchPaddingException e) {
// RSA exists so this should never be thrown
e.printStackTrace();
}
c.init(Cipher.DECRYPT_MODE, privateKey);
dec = c.doFinal(cipher);
return new String(dec, StandardCharsets.UTF_8);
}

Expand All @@ -69,21 +76,21 @@ public static String decrypt(byte[] cipher, PrivateKey privateKey) {
* @param message to be encrypted
* @param publicKey ised to encrypt the data
* @return byte array of encrypted data
* @throws InvalidKeyException in case the key format is not supported
* @throws BadPaddingException in case something failed while padding
* @throws IllegalBlockSizeException in case the blocksize is invalid
*/
public static byte[] encrypt(String message, PublicKey publicKey) {
public static byte[] encrypt(String message, PublicKey publicKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = null;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
} catch (Exception e) {
System.out.println("Error while encrypting: " + e.getMessage());
}
try {
encrypted = cipher.doFinal(message.getBytes("UTF8"));
} catch (IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
System.out.println("Error while encrypting: " + e.getMessage());
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
// RSA exists so this should never be thrown
e.printStackTrace();
}
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encrypted = cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
return encrypted;
}

Expand All @@ -93,19 +100,22 @@ public static byte[] encrypt(String message, PublicKey publicKey) {
* @param privateKey used to sign the data
* @param input data to be signed
* @return Signature as String
* @throws InvalidKeyException in case the key format is not supported
* @throws SignatureException in case something went wrong while creating the signature
*/
public static String sign(PrivateKey privateKey, String input) {
public static String sign(PrivateKey privateKey, String input) throws InvalidKeyException, SignatureException {
Signature privateSignature = null;
try {
Signature privateSignature = Signature.getInstance("SHA256withRSA");
privateSignature.initSign(privateKey);
privateSignature.update(input.getBytes(StandardCharsets.UTF_8));

byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
} catch(Exception e) {
System.err.println("Signing failed: "+e.getMessage());
return null;
privateSignature = Signature.getInstance("SHA256withRSA");
} catch (NoSuchAlgorithmException e) {
// SHA256withRSA exists so this should never be thrown
e.printStackTrace();
}
privateSignature.initSign(privateKey);
privateSignature.update(input.getBytes(StandardCharsets.UTF_8));

byte[] signature = privateSignature.sign();
return Base64.getEncoder().encodeToString(signature);
}

/**
Expand Down Expand Up @@ -134,34 +144,38 @@ public static boolean verifySignature(PublicKey publicKey, String data, String s
* Generates a public key from byte array
* @param key byte array
* @return public key
* @throws InvalidKeySpecException in case the key format is not supported
*/
public static PublicKey generatePublicKeyFromString(byte[] key){
try{
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(key);
KeyFactory kf = KeyFactory.getInstance("RSA");

return kf.generatePublic(X509publicKey);
} catch(Exception e){
e.printStackTrace();
return null;
}
public static PublicKey generatePublicKeyFromString(byte[] key) throws InvalidKeySpecException{
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(key);
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
//should never be thrown
e.printStackTrace();
return null;
}
return kf.generatePublic(X509publicKey);
}

/**
* Generates a private key from byte array
* @param key byte array
* @return private key
* @throws InvalidKeySpecException in case the key format is not supported
*/
public static PrivateKey generatePrivateKeyFromString(byte[] key){
try{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory kf = KeyFactory.getInstance("RSA");

return kf.generatePrivate(pkcs8EncodedKeySpec);
} catch(Exception e){
e.printStackTrace();
return null;
}
public static PrivateKey generatePrivateKeyFromString(byte[] key) throws InvalidKeySpecException{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
// should never be thrown
e.printStackTrace();
return null;
}
return kf.generatePrivate(pkcs8EncodedKeySpec);
}

/**
Expand Down
14 changes: 9 additions & 5 deletions src/main/java/dev/netcode/security/identity/Identity.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,19 @@ public boolean save(Path path) {
/**
* Unlocks a loaded identity which makes it possible to use it
* @param password to unlock the identity with
* @return true if the unlocking process was successful
* @return true if the unlocking process was successful, false otherwise
*/
public boolean unlock(String password) {
var result = AESEncrypter.decrypt(this.privateKey, password);
if(result.wasSuccessful()) {
this.keyPair = new KeyPair(
RSAEncrypter.generatePublicKeyFromString(Base64.getDecoder().decode(this.publicKey)),
RSAEncrypter.generatePrivateKeyFromString(Base64.getDecoder().decode(result.get()))
);
try {
this.keyPair = new KeyPair(
RSAEncrypter.generatePublicKeyFromString(Base64.getDecoder().decode(this.publicKey)),
RSAEncrypter.generatePrivateKeyFromString(Base64.getDecoder().decode(result.get()))
);
} catch(Exception e) {
return false;
}
return true;
}
return false;
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/dev/netcode/security/identity/Signature.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package dev.netcode.security.identity;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.text.SimpleDateFormat;
import java.util.Date;

Expand Down Expand Up @@ -54,8 +57,11 @@ public boolean isValid(PublicKey publicKey, Identity identity) {
/**
* Signs this Signature which makes it valid.
* @param privateKey used to sign the signature
* @throws SignatureException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public void sign(PrivateKey privateKey) {
public void sign(PrivateKey privateKey) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException {
signature = RSAEncrypter.sign(privateKey, getVerifiableDataString());
}

Expand Down