Whats is the Java name for openssl's “aes-256-

2020-02-29 10:07发布

问题:

I'm using openssl's aes-256-cfb algorithm (from NodeJS's crypto module).

While both the NodeJS and the Java code successfully encrypt and decrypt data, the ciphertext is different, even when the iv, key and plaintext are all identical.

openssl/NodeJS cipherText:
05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d

Java cipherText: 
05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D

I have guessed that openssl's aes-256-cfb translates to Java's AES/CFB/NoPadding.

The ciphertexts both share the same initial 9 bytes, which is odd - I would have expected them to share the first 16 bytes if there had been some difference in the common mode used. (I hope that "common mode" is the collective term for CFB/CBC/CTR/etc.)

  • Is Java's AES/CFB/NoPadding the correct translation of OpenSSL's aes-256-cfb?
  • Does the existence of the common first nine bytes imply that Java's AES/CFB/NoPadding is at least using AES256, as opposed to AES128?
  • If so, what else might account for the differing ciphertext?

Test cases follow:

OpenSSL/NodeJS:

var assert = require('assert');
var crypto = require('crypto');

describe('crypto', function() {
  it('should work', function () {
    var plainText = new Buffer('a secret plainText which has more than sixteen bytes');
    var key = new Buffer('fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210', 'hex');
    var iv = new Buffer('0123456789abcdef0123456789abcdef', 'hex');      

    var cipher = crypto.createCipheriv('aes-256-cfb', key, iv);
    var decipher = crypto.createDecipheriv('aes-256-cfb', key, iv);

    var cipherText = cipher.update(plainText);
    cipher.final(); // no need to use this value with cfb, it seems to always be empty?

    assert.equal(plainText.length, cipherText.length);

    assert.equal('05c2aad7bac42ed0846e9a52ce73df9ff9d7ff914feea49fed27d55ad690782a43107914c1b307ec92753227728c95b8e59c546d', cipherText.toString('hex'));

    var deciphered = decipher.update(cipherText);
    decipher.final(); // no need to use value this with cfb, it seems to always be empty?

    assert.equal(plainText, deciphered.toString('utf8'));
  });
});

Java/Android:

import android.test.InstrumentationTestCase;

import com.google.protobuf.ByteString;
import bit.Twiddling;

import java.security.AlgorithmParameters;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class CryptoTest extends InstrumentationTestCase {

    public void test_encrypt_and_decrypt() throws Exception {
        byte[] plainText = "a secret message which has more than sixteen bytes".getBytes();
        byte[] key = Twiddling.hexStringBEToBytes("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
        byte[] iv = Twiddling.hexStringBEToBytes("0123456789abcdef0123456789abcdef");//0123456789abcdef0123456789abcdef");

        SecretKeySpec aesSecret = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
        Cipher decipher = Cipher.getInstance("AES/CFB/NoPadding");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        assertEquals(16, iv.length);

        cipher.init(Cipher.ENCRYPT_MODE, aesSecret, ivps);
        byte[] cipherText = cipher.doFinal(plainText);

        assertEquals(plainText.length, cipherText.length);
        assertEquals("05C2AAD7BAC42ED084739340D47CEC9F03D8E94AC7B1E11A56A6654F76AD2C8076BCA162303E39B44D043732E98FDD28C52D", Twiddling.bytesToHexStringBE(cipherText));

        decipher.init(Cipher.DECRYPT_MODE, aesSecret, ivps);
        byte[] deciphered = decipher.doFinal(cipherText);

        assertEquals(new String(plainText), new String(deciphered));
    }
}

回答1:

It was a find/replace error - the two plainTexts differ after the first nine bytes.

Java's name for OpenSSL's aes-256-cfb is AES/CFB/NoPadding.