change key exchange to ED25519
This commit is contained in:
parent
256721aa12
commit
6afc26e601
11 changed files with 148 additions and 105 deletions
|
@ -1,13 +1,9 @@
|
|||
package common.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import common.network.ILoginHandler;
|
||||
import common.network.Packet;
|
||||
import common.network.PacketBuffer;
|
||||
import common.util.EncryptUtil;
|
||||
|
||||
public class LPacketChallenge implements Packet<ILoginHandler> {
|
||||
private byte[] token;
|
||||
|
@ -15,8 +11,8 @@ public class LPacketChallenge implements Packet<ILoginHandler> {
|
|||
public LPacketChallenge() {
|
||||
}
|
||||
|
||||
public LPacketChallenge(PublicKey pubkey, byte[] token) {
|
||||
this.token = EncryptUtil.encryptData(pubkey, token);
|
||||
public LPacketChallenge(byte[] token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public final void readPacketData(PacketBuffer buf) throws IOException {
|
||||
|
@ -31,7 +27,7 @@ public class LPacketChallenge implements Packet<ILoginHandler> {
|
|||
handler.processChallenge(this);
|
||||
}
|
||||
|
||||
public byte[] getToken(PrivateKey key) {
|
||||
return EncryptUtil.decryptData(key, this.token);
|
||||
public byte[] getToken() {
|
||||
return this.token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package common.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import common.network.ILoginHandler;
|
||||
import common.network.Packet;
|
||||
import common.network.PacketBuffer;
|
||||
import common.util.EncryptUtil;
|
||||
|
||||
public class LPacketResponse implements Packet<ILoginHandler> {
|
||||
private byte[] token = new byte[0];
|
||||
|
@ -11,8 +15,8 @@ public class LPacketResponse implements Packet<ILoginHandler> {
|
|||
public LPacketResponse() {
|
||||
}
|
||||
|
||||
public LPacketResponse(byte[] token) {
|
||||
this.token = token;
|
||||
public LPacketResponse(PrivateKey key, byte[] token) {
|
||||
this.token = EncryptUtil.createSignature(key, token);
|
||||
}
|
||||
|
||||
public void readPacketData(PacketBuffer buf) throws IOException {
|
||||
|
@ -27,7 +31,7 @@ public class LPacketResponse implements Packet<ILoginHandler> {
|
|||
handler.processResponse(this);
|
||||
}
|
||||
|
||||
public byte[] getToken() {
|
||||
return this.token;
|
||||
public boolean verifyToken(PublicKey key, byte[] token) {
|
||||
return EncryptUtil.verifySignature(key, token, this.token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,36 @@
|
|||
package common.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import common.network.ILoginHandler;
|
||||
import common.network.Packet;
|
||||
import common.network.PacketBuffer;
|
||||
import common.util.EncryptUtil;
|
||||
|
||||
public class LPacketStartEncrypt implements Packet<ILoginHandler> {
|
||||
private byte[] key = new byte[0];
|
||||
private byte[] token = new byte[0];
|
||||
private PublicKey key;
|
||||
|
||||
public LPacketStartEncrypt() {
|
||||
}
|
||||
|
||||
public LPacketStartEncrypt(SecretKey secret, PublicKey pubkey, byte[] token) {
|
||||
this.key = EncryptUtil.encryptData(pubkey, secret.getEncoded());
|
||||
this.token = EncryptUtil.encryptData(pubkey, token);
|
||||
public LPacketStartEncrypt(PublicKey pubkey) {
|
||||
this.key = pubkey;
|
||||
}
|
||||
|
||||
public void readPacketData(PacketBuffer buf) throws IOException {
|
||||
this.key = buf.readByteArray();
|
||||
this.token = buf.readByteArray();
|
||||
this.key = EncryptUtil.decodeDHPublicKey(buf.readByteArray());
|
||||
}
|
||||
|
||||
public void writePacketData(PacketBuffer buf) throws IOException {
|
||||
buf.writeByteArray(this.key);
|
||||
buf.writeByteArray(this.token);
|
||||
buf.writeByteArray(this.key.getEncoded());
|
||||
}
|
||||
|
||||
public void processPacket(ILoginHandler handler) {
|
||||
handler.processEncryption(this);
|
||||
}
|
||||
|
||||
public SecretKey getKey(PrivateKey key) {
|
||||
return EncryptUtil.decryptSharedKey(key, this.key);
|
||||
}
|
||||
|
||||
public byte[] getToken(PrivateKey key) {
|
||||
return EncryptUtil.decryptData(key, this.token);
|
||||
public PublicKey getKey() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package common.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import common.network.IClientLoginHandler;
|
||||
import common.network.Packet;
|
||||
import common.network.PacketBuffer;
|
||||
import common.util.EncryptUtil;
|
||||
|
||||
public class RPacketChallenge implements Packet<IClientLoginHandler> {
|
||||
private byte[] token;
|
||||
|
@ -15,8 +11,8 @@ public class RPacketChallenge implements Packet<IClientLoginHandler> {
|
|||
public RPacketChallenge() {
|
||||
}
|
||||
|
||||
public RPacketChallenge(PublicKey pubkey, byte[] token) {
|
||||
this.token = EncryptUtil.encryptData(pubkey, token);
|
||||
public RPacketChallenge(byte[] token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public final void readPacketData(PacketBuffer buf) throws IOException {
|
||||
|
@ -31,7 +27,7 @@ public class RPacketChallenge implements Packet<IClientLoginHandler> {
|
|||
handler.handleChallenge(this);
|
||||
}
|
||||
|
||||
public byte[] getToken(PrivateKey key) {
|
||||
return EncryptUtil.decryptData(key, this.token);
|
||||
public byte[] getToken() {
|
||||
return this.token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,24 +10,24 @@ import common.util.EncryptUtil;
|
|||
|
||||
public class RPacketRequestEncrypt implements Packet<IClientLoginHandler> {
|
||||
private PublicKey key;
|
||||
private byte[] token;
|
||||
private PublicKey tempKey;
|
||||
|
||||
public RPacketRequestEncrypt() {
|
||||
}
|
||||
|
||||
public RPacketRequestEncrypt(PublicKey key, byte[] token) {
|
||||
public RPacketRequestEncrypt(PublicKey key, PublicKey tempKey) {
|
||||
this.key = key;
|
||||
this.token = token;
|
||||
this.tempKey = tempKey;
|
||||
}
|
||||
|
||||
public final void readPacketData(PacketBuffer buf) throws IOException {
|
||||
this.key = EncryptUtil.decodePublicKey(buf.readByteArray());
|
||||
this.token = buf.readByteArray();
|
||||
this.tempKey = EncryptUtil.decodeDHPublicKey(buf.readByteArray());
|
||||
}
|
||||
|
||||
public final void writePacketData(PacketBuffer buf) throws IOException {
|
||||
buf.writeByteArray(this.key.getEncoded());
|
||||
buf.writeByteArray(this.token);
|
||||
buf.writeByteArray(this.tempKey.getEncoded());
|
||||
}
|
||||
|
||||
public void processPacket(IClientLoginHandler handler) {
|
||||
|
@ -38,7 +38,7 @@ public class RPacketRequestEncrypt implements Packet<IClientLoginHandler> {
|
|||
return this.key;
|
||||
}
|
||||
|
||||
public byte[] getToken() {
|
||||
return this.token;
|
||||
public PublicKey getTempKey() {
|
||||
return this.tempKey;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package common.packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import common.network.IClientLoginHandler;
|
||||
import common.network.Packet;
|
||||
import common.network.PacketBuffer;
|
||||
import common.util.EncryptUtil;
|
||||
|
||||
public class RPacketResponse implements Packet<IClientLoginHandler> {
|
||||
private byte[] token = new byte[0];
|
||||
|
@ -11,8 +15,8 @@ public class RPacketResponse implements Packet<IClientLoginHandler> {
|
|||
public RPacketResponse() {
|
||||
}
|
||||
|
||||
public RPacketResponse(byte[] token) {
|
||||
this.token = token;
|
||||
public RPacketResponse(PrivateKey key, byte[] token) {
|
||||
this.token = EncryptUtil.createSignature(key, token);
|
||||
}
|
||||
|
||||
public void readPacketData(PacketBuffer buf) throws IOException {
|
||||
|
@ -27,7 +31,7 @@ public class RPacketResponse implements Packet<IClientLoginHandler> {
|
|||
handler.handleResponse(this);
|
||||
}
|
||||
|
||||
public byte[] getToken() {
|
||||
return this.token;
|
||||
public boolean verifyToken(PublicKey key, byte[] token) {
|
||||
return EncryptUtil.verifySignature(key, token, this.token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
@ -23,7 +25,7 @@ import java.util.Base64;
|
|||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
|
@ -34,28 +36,93 @@ import javax.crypto.spec.SecretKeySpec;
|
|||
import common.log.Log;
|
||||
|
||||
public class EncryptUtil {
|
||||
public static final String KEY_ALGO_NAME = "tcr-ed25519";
|
||||
public static final String KEY_ALGO_DISPLAY = "Ed25519";
|
||||
|
||||
private static final long CRC24_INIT = 0xB704CEL;
|
||||
private static final long CRC24_POLY = 0x1864CFBL;
|
||||
|
||||
public static SecretKey createSharedKey() {
|
||||
// private static byte[] deriveKey(byte[] secret) {
|
||||
// try {
|
||||
// KeySpec spec = new PBEKeySpec
|
||||
// SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
// return factory.generateSecret(spec).getEncoded();
|
||||
// }
|
||||
// catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
// Log.SYSTEM.error(e, "Konnte Passwort-Prüfwert nicht berechnen");
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
public static SecretKey makeKeyAgreement(PrivateKey key, PublicKey pubkey) {
|
||||
try {
|
||||
KeyGenerator keygen = KeyGenerator.getInstance("AES");
|
||||
keygen.init(128);
|
||||
return keygen.generateKey();
|
||||
KeyAgreement agreement = KeyAgreement.getInstance("X25519");
|
||||
agreement.init(key);
|
||||
agreement.doPhase(pubkey, true);
|
||||
return new SecretKeySpec(agreement.generateSecret(), 0, 16, "AES");
|
||||
}
|
||||
catch(NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
Log.SYSTEM.error(e, "Konnte Diffie-Hellman-Schlüsselaushandlung nicht absolvieren");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyPair createDHKeypair() {
|
||||
try {
|
||||
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("X25519");
|
||||
return pairgen.generateKeyPair();
|
||||
}
|
||||
catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
Log.SYSTEM.error(e, "Konnte Schlüsselpaar für Diffie-Hellman nicht generieren");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyPair createKeypair() {
|
||||
try {
|
||||
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
|
||||
pairgen.initialize(4096);
|
||||
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("Ed25519");
|
||||
return pairgen.generateKeyPair();
|
||||
}
|
||||
catch(NoSuchAlgorithmException e) {
|
||||
Log.SYSTEM.error(e, "Konnte Schlüsselpaar nicht generiren");
|
||||
Log.SYSTEM.error(e, "Konnte Schlüsselpaar nicht generieren");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] createSignature(PrivateKey key, byte[] token) {
|
||||
try {
|
||||
Signature sig = Signature.getInstance("Ed25519");
|
||||
sig.initSign(key);
|
||||
sig.update(token);
|
||||
return sig.sign();
|
||||
}
|
||||
catch(SignatureException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
Log.SYSTEM.error(e, "Konnte Signatur nicht generieren");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verifySignature(PublicKey key, byte[] token, byte[] signature) {
|
||||
try {
|
||||
Signature sig = Signature.getInstance("Ed25519");
|
||||
sig.initVerify(key);
|
||||
sig.update(token);
|
||||
return sig.verify(signature);
|
||||
}
|
||||
catch(SignatureException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
Log.SYSTEM.error(e, "Konnte Signatur nicht verifizieren");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static PublicKey decodeDHPublicKey(byte[] encoded) {
|
||||
try {
|
||||
EncodedKeySpec spec = new X509EncodedKeySpec(encoded);
|
||||
KeyFactory factory = KeyFactory.getInstance("X25519");
|
||||
return factory.generatePublic(spec);
|
||||
}
|
||||
catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
Log.SYSTEM.error(e, "Öffentlicher Schlüssel für Diffie-Hellman konnte nicht dekodiert werden");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +130,7 @@ public class EncryptUtil {
|
|||
public static PublicKey decodePublicKey(byte[] encoded) {
|
||||
try {
|
||||
EncodedKeySpec spec = new X509EncodedKeySpec(encoded);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
KeyFactory factory = KeyFactory.getInstance("Ed25519");
|
||||
return factory.generatePublic(spec);
|
||||
}
|
||||
catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
|
@ -75,7 +142,7 @@ public class EncryptUtil {
|
|||
public static PrivateKey decodePrivateKey(byte[] encoded) {
|
||||
try {
|
||||
EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
KeyFactory factory = KeyFactory.getInstance("Ed25519");
|
||||
return factory.generatePrivate(spec);
|
||||
}
|
||||
catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
|
@ -84,10 +151,6 @@ public class EncryptUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static SecretKey decryptSharedKey(PrivateKey key, byte[] secret) {
|
||||
return new SecretKeySpec(decryptData(key, secret), "AES");
|
||||
}
|
||||
|
||||
public static byte[] encryptData(Key key, byte[] data) {
|
||||
return cipher(Cipher.ENCRYPT_MODE, key, data);
|
||||
}
|
||||
|
@ -149,7 +212,7 @@ public class EncryptUtil {
|
|||
}
|
||||
|
||||
public static String getArmoredPubkey(PublicKey pubkey, String cn) {
|
||||
StringBuilder sb = new StringBuilder("tcr-rsa-4096 ");
|
||||
StringBuilder sb = new StringBuilder(EncryptUtil.KEY_ALGO_NAME + " ");
|
||||
sb.append(Base64.getEncoder().encodeToString(pubkey.getEncoded()));
|
||||
sb.append(' ').append(Base64.getEncoder().encodeToString(crc24(pubkey.getEncoded())));
|
||||
return cn == null || cn.isEmpty() ? sb.toString() : sb.append(' ').append(Util.sanitizeCommonName(cn)).toString();
|
||||
|
@ -159,8 +222,8 @@ public class EncryptUtil {
|
|||
String[] tok = armor.trim().split(" ");
|
||||
if(tok.length != 3 && tok.length != 4)
|
||||
throw new IllegalArgumentException("Key muss aus 3 oder 4 Segmenten bestehen");
|
||||
if(!tok[0].equals("tcr-rsa-4096"))
|
||||
throw new IllegalArgumentException("Algorithmus '" + tok[0] + "' ist nicht unterstützt, es wird derzeit nur tcr-rsa-4096 verwendet");
|
||||
if(!tok[0].equals(EncryptUtil.KEY_ALGO_NAME))
|
||||
throw new IllegalArgumentException("Algorithmus '" + tok[0] + "' ist nicht unterstützt, es wird derzeit nur " + EncryptUtil.KEY_ALGO_NAME + " verwendet");
|
||||
byte[] key;
|
||||
try {
|
||||
key = Base64.getDecoder().decode(tok[1]);
|
||||
|
@ -183,7 +246,7 @@ public class EncryptUtil {
|
|||
PublicKey pubkey;
|
||||
try {
|
||||
EncodedKeySpec spec = new X509EncodedKeySpec(key);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
KeyFactory factory = KeyFactory.getInstance("Ed25519");
|
||||
pubkey = factory.generatePublic(spec);
|
||||
}
|
||||
catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue