Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCFB mode reset is incorrect after large data. #1953

Open
tonywasher opened this issue Dec 31, 2024 · 2 comments
Open

GCFB mode reset is incorrect after large data. #1953

tonywasher opened this issue Dec 31, 2024 · 2 comments
Assignees

Comments

@tonywasher
Copy link
Contributor

The GCFB mode calculates a new key and IV after every 1024 bytes processed.

If it is used to encrypt data that is greater than 1024 bytes in length then the subsequent reset (either explicit or implicit on doFinal()), will only reset to the most recent 1024 boundary rather than the original key and IV.

This can be seen via the following code

    /**
     * Data Length. (Anything above 1024 triggers problem).
     */
    private static final int DATALEN = 1025;

    /**
     * SecureRandom.
     */
    private static SecureRandom RANDOM = new SecureRandom();

    /**
     * Main.
     */
    public static void main(final String[] args) {
        try {
            checkCipher(new GCFBBlockCipher(new GOST28147Engine()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Check Cipher.
     * @param pCipher the cipher
     */
    private static void checkCipher(final BlockCipher pCipher) throws Exception {
        /* Create the data */
        final byte[] myData = new byte[DATALEN];
        RANDOM.nextBytes(myData);

        /* Create the Key parameters */
        final CipherKeyGenerator myGenerator = new CipherKeyGenerator();
        final KeyGenerationParameters myGenParams = new KeyGenerationParameters(RANDOM, 256);
        myGenerator.init(myGenParams);
        final byte[] myKey = myGenerator.generateKey();
        final KeyParameter myKeyParams = new KeyParameter(myKey);

        /* Create the IV */
        final byte[] myIV = new byte[16];
        RANDOM.nextBytes(myIV);

        /* Create the initParams */
        final ParametersWithIV myParams = new ParametersWithIV(myKeyParams, myIV);

        /* Wrap Block Cipher with buffered BlockCipher */
        final BufferedBlockCipher myCipher = new DefaultBufferedBlockCipher(pCipher);

        /* Initialise the cipher for encryption */
        myCipher.init(true, myParams);

        /* Encipher the text */
        final byte[] myOutput = new byte[myCipher.getOutputSize(DATALEN)];
        int myOutLen = myCipher.processBytes(myData, 0, DATALEN, myOutput, 0);
        myCipher.doFinal(myOutput, myOutLen);

        /* Re-Encipher the text (after implicit reset) */
        final byte[] myOutput2 = new byte[myCipher.getOutputSize(DATALEN)];
        myOutLen = myCipher.processBytes(myData, 0, DATALEN, myOutput2, 0);
        myCipher.doFinal(myOutput2, myOutLen);

        /* Check that the cipherTexts are identical */
        if (!Arrays.equals(myOutput, myOutput2)) {
            System.out.println("Encryption differs after reset!!")
        }
    }
@dghgit
Copy link
Contributor

dghgit commented Dec 31, 2024

I'm in 2 minds on this one, I'd agree it doesn't work with the JavaDoc but I'm wondering if we should follow the move with GCM to not allow re-use after doFinal. I'll admit I'm not an expert when it comes to GOST, but I can't shake the feeling that the original authors of the standard would regard this as unsafe usage.

Oh and, Happy New Year! I was wondering how far we'd get before the next bug report...

@tonywasher
Copy link
Contributor Author

It may well be better to disable the ability, but GCM only disables re-use after doFinal() on encryption, and does not disable reset(). So if we just copy GCM we will not close down all of this behaviour. I'm not sure that there is huge demand for this mode of operation, so it matters little which way we jump, as long as we do something.

@ligefeiBouncycastle ligefeiBouncycastle self-assigned this Jan 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants