Неправильное шифрование AES

Я пытаюсь создать простой инструмент шифрования AES, который преобразует открытый текст в PSKC5 XML, как показано в главе RFC6030. 6.1. Используя значения примера, показанные в нем, а именно:

  • секрет: 3132333435363738393031323334353637383930
  • ключ шифрования: 12345678901234567890123456789012
  • Ключ MAC: 1122334455667788990011223344556677889900
  • IV для HOTP: 000102030405060708090a0b0c0d0e0f
  • IV для MAC: 11223344556677889900112233445566

Но IV для дайджеста AES слишком длинный, и класс MAC не принимает IV для создания подписи. Я пытался игнорировать MAC IV и конвертировать HOTP IV как

{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}

но я получаю разные результаты от тех, что проиллюстрированы в примере. Это класс, который я использую:

import java.math.BigInteger;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.sun.org.apache.xml.internal.security.utils.Base64;

public class Encrypt {
    private byte[] ivMac, ivHotp, sharedKey, macKey;
    private SecretKey secretSharedKey, secretMacKey;
    private Cipher cipher;
    private AlgorithmParameterSpec cipherParamSpec;
    private Mac mac;

    public Encrypt(String encryptionKey, String macKey, String ivMac, String ivHotp, String csvFilePath) throws FileNotFoundException {
        try {
            this.ivMac = hexStr2Bytes(ivMac);
            this.ivHotp = hexStr2Bytes(ivHotp);
            this.sharedKey = hexStr2Bytes(encryptionKey);
            this.macKey = hexStr2Bytes(macKey);         
            this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            this.mac = Mac.getInstance("HmacSHA1");
            this.mac.init(new SecretKeySpec(this.macKey, "HmacSHA1"));          
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void encryptSingleSecret(String serialNo, String secret) {
        try {
            byte[] secretBytes = hexStr2Bytes(secret);
            String macKeyString = Base64.encode(macKey);
            cipherParamSpec = new IvParameterSpec(this.ivHotp);
            cipher.init(Cipher.ENCRYPT_MODE, new     SecretKeySpec(this.sharedKey, "AES"), cipherParamSpec);
            byte[] secretDigested = cipher.doFinal(secretBytes);
            cipherParamSpec = new IvParameterSpec(this.ivMac);
            cipher.init(Cipher.ENCRYPT_MODE, new     SecretKeySpec(this.sharedKey, "AES"), cipherParamSpec);
            byte[] macDigested = cipher.doFinal(macKey);
            String MacEncrypted = Base64.encode(macDigested);
            String SecretEncrypted = Base64.encode(secretDigested);
            String MacValue =     Base64.encode(mac.doFinal(secretDigested));
            System.out.println("MAC Key: " + MacEncrypted);
            System.out.println("Secret: " + SecretEncrypted);
            System.out.println("MAC ValueMac: " + MacValue);
            return;
        } catch (Exception ex) {
            ex.printStackTrace();
            return;
        }
    }

    /**
     * From RFC 6238 App. A
     * @param hex
     * @return
     */
    public byte[] hexStr2Bytes(String hex) {
        // Adding one byte to get the right conversion
        // Values starting with "0" can be converted
        byte[] bArray = new BigInteger("10" + hex,16).toByteArray();

        // Copy all the REAL bytes, not the "first"
        byte[] ret = new byte[bArray.length - 1];
        for (int i = 0; i < ret.length; i++)
            ret[i] = bArray[i+1];
        return ret;
    }
}

Что я делаю не так?

ОБНОВЛЕНИЕ: Два IV - это IV, которые я должен использовать для шифрования секрета и ключа MAC, соответственно, и они являются шестнадцатеричными массивами, но мои результаты отличаются от показанных в примере. Любая подсказка?

1 ответ

Решение

Я думаю, что вы немного запутались в том, что шифруется, кодируется и т. Д. Я добавил простой метод concatByteArrays, а потом я переписал ваш encryptSingleSecret метод (см. ниже). Одна вещь, которую вы пропустили, - это то, что вы должны добавить IV, который использовался для шифрования чего-либо, к полученному шифру, а затем base64 кодировать весь шебанг. Кроме того, ваше понимание части MAC было немного не так.

private byte [] concatByteArrays(byte []a, byte [] b ) {
    byte [] result = new byte[a.length + b.length];
    System.arraycopy(a, 0, result, 0, a.length);
    System.arraycopy(b, 0, result, a.length, b.length);
    return result;
}

public void encryptSingleSecret(String serialNo, String secret) {
    try {
        byte[] secretBytes = hexStr2Bytes(secret);

        // First, encrypt the MAC key

        cipherParamSpec = new IvParameterSpec(this.ivMac);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(this.sharedKey, "AES"),
                cipherParamSpec);
        byte[] encryptedMacKey = cipher.doFinal(this.macKey);

        // Now, prepend the IV used to encrypt the mac key to the cipher

        byte [] toBeBase64Encoded = concatByteArrays(this.ivMac, encryptedMacKey);

        // Now base64-encode the result and print it out. This is for the
        // <MACKey> element

        System.out.println("<MACKey> <CipherValue>: " + Base64.encode(toBeBase64Encoded));

        // Next, encrypt the secret

        cipherParamSpec = new IvParameterSpec(this.ivHotp);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(this.sharedKey, "AES"),
                cipherParamSpec);
        byte[] encryptedSecret = cipher.doFinal(secretBytes);

        // Now, prepend the IV used to encrypt the secret to the cipher

        toBeBase64Encoded = concatByteArrays(this.ivHotp, encryptedSecret); 

        // Now base64-encode the result and print it out. This is for the
        // <Data> element

        System.out.println("<Data><Secret><CipherValue>: " + Base64.encode(toBeBase64Encoded));

        // Finally, compute the MAC over the encrypted value

        byte [] macValue = this.mac.doFinal(toBeBase64Encoded);

        // Base64-encode the result and print it out. This is for the
        // ValueMAC element

        System.out.println("<Data><Secret><ValueMAC>: " + Base64.encode(macValue));

        return;
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
Другие вопросы по тегам