Cipher#doFinal() mehrere Threads ohne Cipher#update()

FBIagent

Erfahrenes Mitglied
Hallo,

ich habe folgendes Beispiel zusammengebastelt:
Java:
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

public class ApplicationSpecificCipher
{
    private static final Logger _LOGGER = Logger.getLogger(ApplicationSpecificCipher.class.getName());

    /** Static blowfish key to exchange the unique blowfish key for each stream */
    private static final byte[] _STATIC_BLOWFISH_KEY =
    {
        (byte)0x54, (byte)0x25, (byte)0xcf, (byte)0x6f, (byte)0x4c, (byte)0xf6,
        (byte)0xa1, (byte)0xe4, (byte)0x59, (byte)0x2d, (byte)0xd7, (byte)0xb2,
        (byte)0xf4, (byte)0xc7, (byte)0x6c, (byte)0x3f
    };

    private static final String _CIPHER_ALGO = "Blowfish";
    private static final String _CIPHER_INSTANCE_STRING = _CIPHER_ALGO + "/ECB/NoPadding";
    /** En-/Deciphers for first message on each stream to exchange the unique blowfish key */
    private static Cipher _ENCRYPT_CIPHER;
    private static Cipher _DECRYPT_CIPHER;
    private static int _CIPHER_BLOCK_SIZE;

    static
    {
        try
        {
            SecretKeySpec sks = new SecretKeySpec(_STATIC_BLOWFISH_KEY, _CIPHER_ALGO);
            _ENCRYPT_CIPHER = Cipher.getInstance(_CIPHER_INSTANCE_STRING);
            _ENCRYPT_CIPHER.init(Cipher.ENCRYPT_MODE, sks);
            _DECRYPT_CIPHER = Cipher.getInstance(_CIPHER_INSTANCE_STRING);
            _DECRYPT_CIPHER.init(Cipher.DECRYPT_MODE, sks);
            _CIPHER_BLOCK_SIZE = _ENCRYPT_CIPHER.getBlockSize();
        }
        catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException ex)
        {
            _LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
            System.exit(1);
        }
    }

    private Cipher _encryptCipher = null;
    private Cipher _decryptCipher = null;

    public void setUniqueKey(byte[] blowfishKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException
    {
        SecretKeySpec sks = new SecretKeySpec(blowfishKey, _CIPHER_ALGO);
        _encryptCipher = Cipher.getInstance(_CIPHER_INSTANCE_STRING);
        _encryptCipher.init(Cipher.ENCRYPT_MODE, sks);
        _decryptCipher = Cipher.getInstance(_CIPHER_INSTANCE_STRING);
        _decryptCipher.init(Cipher.DECRYPT_MODE, sks);
    }

    public void encipher(byte[] src, int srcOff, byte[] dst, int dstOff, int len) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
    {
        if (_encryptCipher == null)
            _ENCRYPT_CIPHER.doFinal(src, srcOff, len, dst, dstOff);
        else
            _encryptCipher.doFinal(src, srcOff, len, dst, dstOff);
    }

    public void decipher(byte[] src, int srcOff, byte[] dst, int dstOff, int len) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
    {
        if (_decryptCipher == null)
            _DECRYPT_CIPHER.doFinal(src, srcOff, len, dst, dstOff);
        else
            _decryptCipher.doFinal(src, srcOff, len, dst, dstOff);
    }

    public int getRequiredPadding(int len)
    {
        return _CIPHER_BLOCK_SIZE - (len % _CIPHER_BLOCK_SIZE);
    }
}

Scenario:
1. Der Server nimmt Verbindungenen von Klienten über TCP an
2. Jede Klientverbindung bekommt vom Server zu aller erst eine Kleine Menge an Daten,
die mit dem Blowfish Algorythmus verschlüsselt wurden. Der Schlüssel ist hierbei immer der
gleiche, da mit diesen ersten Daten der, für jede Verbindung, einzigartige Schlüssel gesendet wird, mit dem die darauffolgenden Daten Verschlüsselt werden.

Da sich der interne Status des Blowfish Ciphers zum verschlüsseln/entschlüsseln nicht
ändert(verbessert mich bitte falls ich falsch liege) sollte es doch in irgend einer Weise
möglich sein hier für die ersten übermittelten Daten ein statisches Cipher Objekt zu
erstellen und immer damit zu verschlüsseln/entschlüsseln.

In der Dokumentation steht das Cipher#doFinal() immer nacheinander aufgerufen werden muss.
Allerdings wäre es Verschwendung von Resourcen bei jeder neuen Verbindung ein neues Cipher
Object zu erstellen, da der Schlüssel für die ersten Daten ja immer gleich bleibt.

Gibt es da einen Weg?
 
Zuletzt bearbeitet:
Zurück