Почему зашифрованный текст длиной 32 байта при шифровании 16 байтов с помощью AES? - PullRequest
11 голосов
/ 26 июня 2011

Я использую алгоритм шифрования AES, когда я шифрую 16 байт (один блок), результат составляет 32 байта.Это нормально?

Мой исходный код, который я использовал:

<code>package net.sf.andhsli.hotspotlogin;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * Usage:
 * <pre>
 * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
 * ...
 * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
 * 
* @author ferenc.hechler * / public class SimpleCrypto {public static String encrypt (String seed, String cleartext) выдает Exception {byte [] rawKey = getRawKey (seed.getBytes ());byte [] result = encrypt (rawKey, cleartext.getBytes ());возврат к Hex (результат);} public static String decrypt (String seed, String encrypted) создает исключение {byte [] rawKey = getRawKey (seed.getBytes ());byte [] enc = toByte (зашифрованный);byte [] result = decrypt (rawKey, enc);вернуть новую строку (результат);} закрытый статический byte [] getRawKey (byte [] seed) создает исключение {KeyGenerator kgen = KeyGenerator.getInstance ("AES");SecureRandom sr = SecureRandom.getInstance ("SHA1PRNG");sr.setSeed (семян);kgen.init (128, ср);// 192 и 256 битов могут быть недоступны SecretKey skey = kgen.generateKey ();byte [] raw = skey.getEncoded ();вернуть сырье;} private static byte [] encrypt (byte [] raw, byte [] clear) создает исключение {SecretKeySpec skeySpec = new SecretKeySpec (raw, "AES");Cipher cipher = Cipher.getInstance ("AES");cipher.init (Cipher.ENCRYPT_MODE, skeySpec);byte [] encrypted = cipher.doFinal (clear);возврат зашифрован;} частный статический byte [] decrypt (byte [] raw, byte [] зашифрованный) создает исключение {SecretKeySpec skeySpec = new SecretKeySpec (raw, "AES");Cipher cipher = Cipher.getInstance ("AES");cipher.init (Cipher.DECRYPT_MODE, skeySpec);byte [] decrypted = cipher.doFinal (зашифрованный);возврат расшифрован;} public static String toHex (String txt) {return toHex (txt.getBytes ());} public static String fromHex (String hex) {return new String (toByte (hex));} открытый статический byte [] toByte (String hexString) {int len ​​= hexString.length () / 2;байт [] результат = новый байт [лен];для (int i = 0; i > 4) & 0x0f)). append (HEX.charAt (b & 0x0f));}}

Ответы [ 3 ]

15 голосов
/ 26 июня 2011

Если вы посмотрите на секцию спецификации 5 , то увидите, что вход, выход и состояние все 128-битные.Единственное, что меняется, - это размер ключа: 128, 196 или 256 бит.Таким образом, шифрование 16-байтового состояния ввода даст 16-байтовое состояние вывода.

Вы уверены, что не смешиваете его с длиной в шестнадцатеричной записи или чем-то подобным?Если он указан в шестнадцатеричной системе счисления, то он правильный, потому что для каждого байта для его представления необходимы два символа: 00-FF (для диапазона 0-255).

Другой способ проверить правильность шифрования:выполнив эквивалентную расшифровку, посмотрите, соответствует ли она текстовой входной строке.

В любом случае, она делает правильные вещи.Вот тест:

public static void main(String[] args) {
  try {
    String plaintext = "Hello world", key = "test";
    String ciphertext = encrypt(key, plaintext);
    String plaintext2 = decrypt(key, ciphertext);
    System.out.println("Encrypting '" + plaintext +
                       "' yields: (" + ciphertext.length() + ") " + ciphertext);
    System.out.println("Decrypting it yields: " + plaintext2);
  }
  catch (Exception ex) {
      ex.printStackTrace();
  }
}

Который дает:

Шифрование приводит к «Hello world»: (32) 5B68978D821FCA6022D4B90081F76B4F

Расшифровывая это приводит к: Hello world

6 голосов
/ 27 июня 2011

AES по умолчанию использует шифрование в режиме ECB с PKCS # 7-совместимым режимом заполнения (для всех провайдеров , наблюдаемых до сих пор). Для шифрования в режиме ECB и CBC требуется заполнение, если входное значение не кратно размеру блока, а 16 - это размер блока AES в байтах.

К сожалению, для механизма распаковки может не быть возможности различить заполнение и данные; сами данные могут представлять действительный отступ. Таким образом, для 16 байтов ввода вы получите еще 16 байтов заполнения. Детерминированные режимы заполнения, такие как PKCS # 7 , всегда заполнены с байтами от 1 до [размера блока].

Если вы посмотрите на int output = cipher.getOutputSize(16);, вы получите 32 байта. Используйте "AES/ECB/NoPadding" во время дешифрования, чтобы увидеть байты заполнения (например, 4D61617274656E20426F64657765732110101010101010101010101010101010).

Вам лучше, когда вы полностью укажете алгоритм ("AES/CBC/PKCS5Padding" используется нормально). В противном случае вы будете продолжать угадывать, какой режим на самом деле используется.

Обратите внимание, что использование режима ECB небезопасно, поскольку злоумышленник может извлечь информацию из зашифрованного текста. Одинаковые блоки простого текста кодируются в идентичные блоки зашифрованного текста.

0 голосов
/ 19 ноября 2013
package com.cipher;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Encrypt {

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        // TODO Auto-generated method stub
String s="You are doing encryption at deep level";
SecureRandom sr=SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(s.getBytes());
byte[] k=new byte[128/8];
sr.nextBytes(k);
SecretKeySpec spec=new SecretKeySpec(k,"AES");
byte[] iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
IvParameterSpec ivs=new IvParameterSpec(iv);
Cipher cps=Cipher.getInstance("AES/CBC/PKCS5Padding");
cps.init(Cipher.ENCRYPT_MODE,spec,ivs);
byte[] iv2=cps.doFinal(s.getBytes());
System.out.println("En"+iv2);
Cipher cpr=Cipher.getInstance("AES/CBC/PKCS5Padding");
cpr.init(Cipher.DECRYPT_MODE, spec,ivs);
byte[] iv3=cpr.doFinal(iv2);
String ds=new String(iv3);
System.out.println(ds);


    }

}
...