diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index 281e5d46..cf0ec0b0 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -81,13 +81,9 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab * This object contains runtime configuration */ public final LaunchServerRuntimeConfig runtime; - /** - * Public ECDSA LaunchServer key - */ + @Deprecated public final ECPublicKey publicKey; - /** - * Private ECDSA LaunchServer key - */ + @Deprecated public final ECPrivateKey privateKey; /** * Pipeline for building JAR @@ -110,6 +106,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab public final ConfigManager configManager; public final PingServerManager pingServerManager; public final FeaturesManager featuresManager; + public final KeyAgreementManager keyAgreementManager; // HWID ban + anti-brutforce public final CertificateManager certificateManager; // Server @@ -123,7 +120,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab // Updates and profiles private volatile List profilesList; - public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, ECPublicKey publicKey, ECPrivateKey privateKey, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException { + public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException { this.dir = directories.dir; this.env = env; this.config = config; @@ -131,8 +128,9 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La this.modulesManager = modulesManager; this.profilesDir = directories.profilesDir; this.updatesDir = directories.updatesDir; - this.publicKey = publicKey; - this.privateKey = privateKey; + this.keyAgreementManager = keyAgreementManager; + this.publicKey = keyAgreementManager.ecdsaPublicKey; + this.privateKey = keyAgreementManager.ecdsaPrivateKey; this.commandHandler = commandHandler; this.runtime = runtimeConfig; this.certificateManager = certificateManager; @@ -510,11 +508,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO public static class LaunchServerDirectories { public static final String UPDATES_NAME = "updates", PROFILES_NAME = "profiles", TRUSTSTORE_NAME = "truststore", LAUNCHERLIBRARIES_NAME = "launcher-libraries", - LAUNCHERLIBRARIESCOMPILE_NAME = "launcher-libraries-compile"; + LAUNCHERLIBRARIESCOMPILE_NAME = "launcher-libraries-compile", KEY_NAME = ".keys"; public Path updatesDir; public Path profilesDir; public Path launcherLibrariesDir; public Path launcherLibrariesCompileDir; + public Path keyDirectory; public Path dir; public Path trustStore; @@ -525,6 +524,7 @@ public void collect() { if (launcherLibrariesDir == null) launcherLibrariesDir = dir.resolve(LAUNCHERLIBRARIES_NAME); if (launcherLibrariesCompileDir == null) launcherLibrariesCompileDir = dir.resolve(LAUNCHERLIBRARIESCOMPILE_NAME); + if(keyDirectory == null) keyDirectory = dir.resolve(KEY_NAME); } } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java index 047bb607..eb6ad544 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java @@ -3,6 +3,7 @@ import pro.gravit.launchserver.config.LaunchServerConfig; import pro.gravit.launchserver.config.LaunchServerRuntimeConfig; import pro.gravit.launchserver.manangers.CertificateManager; +import pro.gravit.launchserver.manangers.KeyAgreementManager; import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager; import pro.gravit.utils.command.CommandHandler; @@ -17,8 +18,7 @@ public class LaunchServerBuilder { private LaunchServer.LaunchServerEnv env; private LaunchServerModulesManager modulesManager; private LaunchServer.LaunchServerDirectories directories = new LaunchServer.LaunchServerDirectories(); - private ECPublicKey publicKey; - private ECPrivateKey privateKey; + private KeyAgreementManager keyAgreementManager; private CertificateManager certificateManager; private LaunchServer.LaunchServerConfigManager launchServerConfigManager; @@ -57,16 +57,6 @@ public LaunchServerBuilder setDir(Path dir) { return this; } - public LaunchServerBuilder setPublicKey(ECPublicKey publicKey) { - this.publicKey = publicKey; - return this; - } - - public LaunchServerBuilder setPrivateKey(ECPrivateKey privateKey) { - this.privateKey = privateKey; - return this; - } - public LaunchServerBuilder setLaunchServerConfigManager(LaunchServer.LaunchServerConfigManager launchServerConfigManager) { this.launchServerConfigManager = launchServerConfigManager; return this; @@ -97,11 +87,18 @@ public void writeRuntimeConfig(LaunchServerRuntimeConfig config) { } }; } - return new LaunchServer(directories, env, config, runtimeConfig, launchServerConfigManager, modulesManager, publicKey, privateKey, commandHandler, certificateManager); + if(keyAgreementManager == null) { + keyAgreementManager = new KeyAgreementManager(directories.keyDirectory); + } + return new LaunchServer(directories, env, config, runtimeConfig, launchServerConfigManager, modulesManager, keyAgreementManager, commandHandler, certificateManager); } public LaunchServerBuilder setCertificateManager(CertificateManager certificateManager) { this.certificateManager = certificateManager; return this; } + + public void setKeyAgreementManager(KeyAgreementManager keyAgreementManager) { + this.keyAgreementManager = keyAgreementManager; + } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java index 9b952854..5dc95b7b 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java @@ -120,11 +120,11 @@ public static void main(String[] args) throws Exception { } if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) { LogHelper.info("Reading EC keypair"); - publicKey = SecurityHelper.toPublicECKey(IOHelper.read(publicKeyFile)); - privateKey = SecurityHelper.toPrivateECKey(IOHelper.read(privateKeyFile)); + publicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(publicKeyFile)); + privateKey = SecurityHelper.toPrivateECDSAKey(IOHelper.read(privateKeyFile)); } else { LogHelper.info("Generating EC keypair"); - KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); + KeyPair pair = SecurityHelper.genECDSAKeyPair(new SecureRandom()); publicKey = (ECPublicKey) pair.getPublic(); privateKey = (ECPrivateKey) pair.getPrivate(); @@ -202,8 +202,6 @@ public void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOExcept .setDirectories(directories) .setEnv(env) .setCommandHandler(localCommandHandler) - .setPrivateKey(privateKey) - .setPublicKey(publicKey) .setRuntimeConfig(runtimeConfig) .setConfig(config) .setModulesManager(modulesManager) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/interfaces/SecureProtectHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/interfaces/SecureProtectHandler.java index 0170bba9..55444083 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/interfaces/SecureProtectHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/interfaces/SecureProtectHandler.java @@ -19,7 +19,7 @@ default byte[] generateSecureLevelKey() { default void verifySecureLevelKey(byte[] publicKey, byte[] data, byte[] signature) throws InvalidKeySpecException, SignatureException { if (publicKey == null || signature == null) throw new InvalidKeySpecException(); - ECPublicKey pubKey = SecurityHelper.toPublicECKey(publicKey); + ECPublicKey pubKey = SecurityHelper.toPublicECDSAKey(publicKey); Signature sign = SecurityHelper.newECVerifySignature(pubKey); sign.update(data); sign.verify(signature); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java index af8d398f..0e211e9e 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java @@ -11,7 +11,6 @@ public abstract class LauncherBinary extends BinaryPipeline { public final LaunchServer server; public final Path syncBinaryFile; private volatile byte[] digest; - private volatile byte[] sign; protected LauncherBinary(LaunchServer server, Path binaryFile, String nameFormat) { super(server.dir.resolve("build"), nameFormat); @@ -35,17 +34,12 @@ public final byte[] getDigest() { return digest; } - public final byte[] getSign() { - return sign; - } - public void init() { } public final boolean sync() throws IOException { boolean exists = exists(); digest = exists ? SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA512, IOHelper.read(syncBinaryFile)) : null; - sign = exists ? SecurityHelper.sign(IOHelper.read(syncBinaryFile), server.privateKey) : null; return exists; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/KeyAgreementManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/KeyAgreementManager.java new file mode 100644 index 00000000..c31755e1 --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/KeyAgreementManager.java @@ -0,0 +1,63 @@ +package pro.gravit.launchserver.manangers; + +import pro.gravit.utils.helper.IOHelper; +import pro.gravit.utils.helper.LogHelper; +import pro.gravit.utils.helper.SecurityHelper; + +import java.io.IOException; +import java.nio.file.Path; +import java.security.*; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; + +public class KeyAgreementManager { + public final ECPublicKey ecdsaPublicKey; + public final ECPrivateKey ecdsaPrivateKey; + public final RSAPublicKey rsaPublicKey; + public final RSAPrivateKey rsaPrivateKey; + + public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivateKey, RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey) { + this.ecdsaPublicKey = ecdsaPublicKey; + this.ecdsaPrivateKey = ecdsaPrivateKey; + this.rsaPublicKey = rsaPublicKey; + this.rsaPrivateKey = rsaPrivateKey; + } + + public KeyAgreementManager(Path keyDirectory) throws IOException, InvalidKeySpecException { + Path ecdsaPublicKeyPath = keyDirectory.resolve("ecdsa_id.pub"), ecdsaPrivateKeyPath = keyDirectory.resolve("ecdsa_id"); + if (IOHelper.isFile(ecdsaPublicKeyPath) && IOHelper.isFile(ecdsaPrivateKeyPath)) { + LogHelper.info("Reading ECDSA keypair"); + ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(ecdsaPublicKeyPath)); + ecdsaPrivateKey = SecurityHelper.toPrivateECDSAKey(IOHelper.read(ecdsaPrivateKeyPath)); + } else { + LogHelper.info("Generating ECDSA keypair"); + KeyPair pair = SecurityHelper.genECDSAKeyPair(new SecureRandom()); + ecdsaPublicKey = (ECPublicKey) pair.getPublic(); + ecdsaPrivateKey = (ECPrivateKey) pair.getPrivate(); + + // Write key pair list + LogHelper.info("Writing ECDSA keypair list"); + IOHelper.write(ecdsaPublicKeyPath, ecdsaPublicKey.getEncoded()); + IOHelper.write(ecdsaPrivateKeyPath, ecdsaPrivateKey.getEncoded()); + } + Path rsaPublicKeyPath = keyDirectory.resolve("rsa_id.pub"), rsaPrivateKeyPath = keyDirectory.resolve("rsa_id"); + if (IOHelper.isFile(rsaPublicKeyPath) && IOHelper.isFile(rsaPrivateKeyPath)) { + LogHelper.info("Reading RSA keypair"); + rsaPublicKey = SecurityHelper.toPublicRSAKey(IOHelper.read(rsaPublicKeyPath)); + rsaPrivateKey = SecurityHelper.toPrivateRSAKey(IOHelper.read(rsaPrivateKeyPath)); + } else { + LogHelper.info("Generating RSA keypair"); + KeyPair pair = SecurityHelper.genRSAKeyPair(new SecureRandom()); + rsaPublicKey = (RSAPublicKey) pair.getPublic(); + rsaPrivateKey = (RSAPrivateKey) pair.getPrivate(); + + // Write key pair list + LogHelper.info("Writing RSA keypair list"); + IOHelper.write(rsaPublicKeyPath, rsaPublicKey.getEncoded()); + IOHelper.write(rsaPrivateKeyPath, rsaPrivateKey.getEncoded()); + } + } +} diff --git a/LaunchServer/src/test/java/pro/gravit/launchserver/ConfigurationTest.java b/LaunchServer/src/test/java/pro/gravit/launchserver/ConfigurationTest.java index 61badc26..63ffc19f 100644 --- a/LaunchServer/src/test/java/pro/gravit/launchserver/ConfigurationTest.java +++ b/LaunchServer/src/test/java/pro/gravit/launchserver/ConfigurationTest.java @@ -1,5 +1,6 @@ package pro.gravit.launchserver; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -26,6 +27,7 @@ import java.nio.file.Path; import java.security.KeyPair; import java.security.SecureRandom; +import java.security.Security; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; @@ -41,22 +43,18 @@ public class ConfigurationTest { @BeforeAll public static void prepare() throws Throwable { + if(Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider()); LaunchServerModulesManager modulesManager = new LaunchServerModulesManager(modulesDir, configDir, null); LaunchServerConfig config = LaunchServerConfig.getDefault(LaunchServer.LaunchServerEnv.TEST); Launcher.gsonManager = new LaunchServerGsonManager(modulesManager); Launcher.gsonManager.initGson(); LaunchServerRuntimeConfig runtimeConfig = new LaunchServerRuntimeConfig(); LaunchServerBuilder builder = new LaunchServerBuilder(); - KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); - ECPublicKey publicKey = (ECPublicKey) pair.getPublic(); - ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate(); launchServerConfigManager = new TestLaunchServerConfigManager(); builder.setDir(dir) .setEnv(LaunchServer.LaunchServerEnv.TEST) .setConfig(config) .setRuntimeConfig(runtimeConfig) - .setPublicKey(publicKey) - .setPrivateKey(privateKey) .setCertificateManager(new CertificateManager()) .setLaunchServerConfigManager(launchServerConfigManager) .setModulesManager(modulesManager) diff --git a/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java b/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java index a2882655..7c251927 100644 --- a/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java +++ b/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java @@ -1,5 +1,6 @@ package pro.gravit.launchserver; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -17,6 +18,7 @@ import java.nio.file.Path; import java.security.KeyPair; import java.security.SecureRandom; +import java.security.Security; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; @@ -31,21 +33,17 @@ public class StartLaunchServerTest { @BeforeAll public static void prepare() throws Throwable { + if(Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider()); LaunchServerModulesManager modulesManager = new LaunchServerModulesManager(modulesDir, configDir, null); LaunchServerConfig config = LaunchServerConfig.getDefault(LaunchServer.LaunchServerEnv.TEST); Launcher.gsonManager = new LaunchServerGsonManager(modulesManager); Launcher.gsonManager.initGson(); LaunchServerRuntimeConfig runtimeConfig = new LaunchServerRuntimeConfig(); LaunchServerBuilder builder = new LaunchServerBuilder(); - KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); - ECPublicKey publicKey = (ECPublicKey) pair.getPublic(); - ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate(); builder.setDir(dir) .setEnv(LaunchServer.LaunchServerEnv.TEST) .setConfig(config) .setRuntimeConfig(runtimeConfig) - .setPublicKey(publicKey) - .setPrivateKey(privateKey) .setCertificateManager(new CertificateManager()) .setLaunchServerConfigManager(new TestLaunchServerConfigManager()) .setModulesManager(modulesManager) diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 9b0d6fb6..d4a378b7 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -151,11 +151,11 @@ public void readKeys() throws IOException, InvalidKeySpecException { Path privateKeyFile = dir.resolve("private.key"); if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) { LogHelper.info("Reading EC keypair"); - publicKey = SecurityHelper.toPublicECKey(IOHelper.read(publicKeyFile)); - privateKey = SecurityHelper.toPrivateECKey(IOHelper.read(privateKeyFile)); + publicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(publicKeyFile)); + privateKey = SecurityHelper.toPrivateECDSAKey(IOHelper.read(privateKeyFile)); } else { LogHelper.info("Generating EC keypair"); - KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); + KeyPair pair = SecurityHelper.genECDSAKeyPair(new SecureRandom()); publicKey = (ECPublicKey) pair.getPublic(); privateKey = (ECPrivateKey) pair.getPrivate(); diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java index bd45f1b0..17763824 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java @@ -52,7 +52,7 @@ public final class LauncherConfig extends StreamObject { @LauncherInjectionConstructor public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException { - publicKey = SecurityHelper.toPublicECKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); + publicKey = SecurityHelper.toPublicECDSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); secureCheckHash = null; secureCheckSalt = null; passwordEncryptKey = null; diff --git a/LauncherCore/src/main/java/pro/gravit/utils/helper/SecurityHelper.java b/LauncherCore/src/main/java/pro/gravit/utils/helper/SecurityHelper.java index 70d11eba..0221741b 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/helper/SecurityHelper.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/helper/SecurityHelper.java @@ -1,5 +1,7 @@ package pro.gravit.utils.helper; +import org.bouncycastle.jcajce.provider.asymmetric.RSA; + import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; @@ -10,13 +12,8 @@ import java.net.URL; import java.nio.file.Path; import java.security.*; -import java.security.interfaces.ECKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; +import java.security.interfaces.*; +import java.security.spec.*; import java.util.HashMap; import java.util.Map; import java.util.Random; @@ -28,10 +25,14 @@ public final class SecurityHelper { // EC Algorithm constants public static final String EC_CURVE = "secp256r1"; public static final String EC_SIGN_ALGO = "SHA256withECDSA"; - public static final String EC_CIPHER_ALGO = "ECIES"; public static final int TOKEN_LENGTH = 16; // RSA Algorithm constants + + public static final String RSA_ALGO = "RSA"; + public static final String RSA_SIGN_ALGO = "SHA256withRSA"; + public static final String RSA_CIPHER_ALGO = "RSA/ECB/PKCS1Padding"; + // Algorithm size constants public static final int AES_KEY_LENGTH = 8; public static final int TOKEN_STRING_LENGTH = TOKEN_LENGTH << 1; @@ -81,7 +82,12 @@ public static byte[] digest(DigestAlgorithm algo, URL url) throws IOException { } } + @Deprecated public static KeyPair genECKeyPair(SecureRandom random) { + return genECDSAKeyPair(random); + } + + public static KeyPair genECDSAKeyPair(SecureRandom random) { try { KeyPairGenerator generator = KeyPairGenerator.getInstance(EC_ALGO); generator.initialize(new ECGenParameterSpec(EC_CURVE), random); @@ -91,6 +97,18 @@ public static KeyPair genECKeyPair(SecureRandom random) { } } + public static KeyPair genRSAKeyPair(SecureRandom random) { + try { + KeyPairGenerator generator = KeyPairGenerator.getInstance(RSA_ALGO); + generator.initialize(RSA_KEY_LENGTH_BITS, random); + return generator.genKeyPair(); + } catch (NoSuchAlgorithmException e) { + throw new InternalError(e); + } + } + + + public static boolean isValidSign(byte[] bytes, byte[] sign, ECPublicKey publicKey) throws SignatureException { Signature signature = newECVerifySignature(publicKey); @@ -109,6 +127,23 @@ public static boolean isValidSign(InputStream input, byte[] sign, ECPublicKey pu return signature.verify(sign); } + public static boolean isValidSign(byte[] bytes, byte[] sign, RSAPublicKey publicKey) throws SignatureException { + Signature signature = newRSAVerifySignature(publicKey); + try { + signature.update(bytes); + } catch (SignatureException e) { + throw new InternalError(e); + } + return signature.verify(sign); + } + + + public static boolean isValidSign(InputStream input, byte[] sign, RSAPublicKey publicKey) throws IOException, SignatureException { + Signature signature = newRSAVerifySignature(publicKey); + updateSignature(input, signature); + return signature.verify(sign); + } + public static boolean isValidToken(CharSequence token) { return token.length() == TOKEN_STRING_LENGTH && token.chars().allMatch(ch -> HEX.indexOf(ch) >= 0); @@ -150,8 +185,8 @@ public static SecureRandom newRandom() { return new SecureRandom(); } - private static Cipher newECCipher(int mode, ECKey key) { - Cipher cipher = newBCCipher(EC_CIPHER_ALGO); + private static Cipher newRSACipher(int mode, RSAKey key) { + Cipher cipher = newCipher(RSA_CIPHER_ALGO); try { cipher.init(mode, (Key) key); } catch (InvalidKeyException e) { @@ -160,7 +195,7 @@ private static Cipher newECCipher(int mode, ECKey key) { return cipher; } - private static KeyFactory newECKeyFactory() { + private static KeyFactory newECDSAKeyFactory() { try { return KeyFactory.getInstance(EC_ALGO); } catch (NoSuchAlgorithmException e) { @@ -168,6 +203,14 @@ private static KeyFactory newECKeyFactory() { } } + private static KeyFactory newRSAKeyFactory() { + try { + return KeyFactory.getInstance(RSA_ALGO); + } catch (NoSuchAlgorithmException e) { + throw new InternalError(e); + } + } + private static Signature newECSignature() { try { return Signature.getInstance(EC_SIGN_ALGO); @@ -176,6 +219,14 @@ private static Signature newECSignature() { } } + private static Signature newRSASignature() { + try { + return Signature.getInstance(RSA_SIGN_ALGO); + } catch (NoSuchAlgorithmException e) { + throw new InternalError(e); + } + } + public static Signature newECSignSignature(ECPrivateKey key) { Signature signature = newECSignature(); try { @@ -186,6 +237,16 @@ public static Signature newECSignSignature(ECPrivateKey key) { return signature; } + public static Signature newRSASignSignature(RSAPrivateKey key) { + Signature signature = newRSASignature(); + try { + signature.initSign(key); + } catch (InvalidKeyException e) { + throw new InternalError(e); + } + return signature; + } + public static Signature newECVerifySignature(ECPublicKey key) { Signature signature = newECSignature(); @@ -197,6 +258,16 @@ public static Signature newECVerifySignature(ECPublicKey key) { return signature; } + public static Signature newRSAVerifySignature(RSAPublicKey key) { + Signature signature = newRSASignature(); + try { + signature.initVerify(key); + } catch (InvalidKeyException e) { + throw new InternalError(e); + } + return signature; + } + public static byte[] randomBytes(int length) { return randomBytes(newRandom(), length); @@ -336,12 +407,30 @@ public static String toHex(byte[] bytes) { return new String(hex); } + @Deprecated public static ECPublicKey toPublicECKey(byte[] bytes) throws InvalidKeySpecException { - return (ECPublicKey) newECKeyFactory().generatePublic(new X509EncodedKeySpec(bytes)); + return toPublicECDSAKey(bytes); } + @Deprecated public static ECPrivateKey toPrivateECKey(byte[] bytes) throws InvalidKeySpecException { - return (ECPrivateKey) newECKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes)); + return toPrivateECDSAKey(bytes); + } + + public static ECPublicKey toPublicECDSAKey(byte[] bytes) throws InvalidKeySpecException { + return (ECPublicKey) newECDSAKeyFactory().generatePublic(new X509EncodedKeySpec(bytes)); + } + + public static ECPrivateKey toPrivateECDSAKey(byte[] bytes) throws InvalidKeySpecException { + return (ECPrivateKey) newECDSAKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes)); + } + + public static RSAPublicKey toPublicRSAKey(byte[] bytes) throws InvalidKeySpecException { + return (RSAPublicKey) newRSAKeyFactory().generatePublic(new X509EncodedKeySpec(bytes)); + } + + public static RSAPrivateKey toPrivateRSAKey(byte[] bytes) throws InvalidKeySpecException { + return (RSAPrivateKey) newRSAKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes)); } private static void updateSignature(InputStream input, Signature signature) throws IOException { @@ -366,22 +455,33 @@ public static void verifySign(InputStream input, byte[] sign, ECPublicKey public throw new SignatureException("Invalid stream sign"); } + public static void verifySign(byte[] bytes, byte[] sign, RSAPublicKey publicKey) throws SignatureException { + if (!isValidSign(bytes, sign, publicKey)) + throw new SignatureException("Invalid sign"); + } + + + public static void verifySign(InputStream input, byte[] sign, RSAPublicKey publicKey) throws SignatureException, IOException { + if (!isValidSign(input, sign, publicKey)) + throw new SignatureException("Invalid stream sign"); + } + public static String verifyToken(String token) { return VerifyHelper.verify(token, SecurityHelper::isValidToken, String.format("Invalid token: '%s'", token)); } - public static Cipher newECDecryptCipher(ECPrivateKey privateKey) { + public static Cipher newRSADecryptCipher(RSAPrivateKey privateKey) { try { - return newECCipher(Cipher.DECRYPT_MODE, privateKey); + return newRSACipher(Cipher.DECRYPT_MODE, privateKey); } catch (SecurityException e) { throw new InternalError(e); } } - public static Cipher newECEncryptCipher(ECPublicKey publicKey) { + public static Cipher newRSAEncryptCipher(RSAPublicKey publicKey) { try { - return newECCipher(Cipher.ENCRYPT_MODE, publicKey); + return newRSACipher(Cipher.ENCRYPT_MODE, publicKey); } catch (SecurityException e) { throw new InternalError(e); }