为什么使用AES加密16个字节时,密文32字节长? [英] Why is the ciphertext 32 bytes long when encrypting 16 bytes with AES?

查看:434
本文介绍了为什么使用AES加密16个字节时,密文32字节长?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用加密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;

/ **
*用法:
*< pre>
* String crypto = SimpleCrypto.encrypt(masterpassword,cleartext)
* ...
* String cleartext = SimpleCrypto.decrypt(masterpassword,crypto)
*< / pre>
* @author ferenc.hechler
* /
public class SimpleCrypto {

public static String encrypt(String seed,String cleartext)throws Exception {
byte [] rawKey = getRawKey(seed.getBytes());
byte [] result = encrypt(rawKey,cleartext.getBytes());
return toHex(result);
}

public static String decrypt(String seed,String encrypted)throws异常{
byte [] rawKey = getRawKey(seed.getBytes());
byte [] enc = toByte(encrypted);
byte [] result = decrypt(rawKey,enc);
return new String(result);
}

private static byte [] getRawKey(byte [] seed)throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(AES);
SecureRandom sr = SecureRandom.getInstance(SHA1PRNG);
sr.setSeed(seed);
kgen.init(128,sr); // 192和256位可能不可用
SecretKey skey = kgen.generateKey();
byte [] raw = skey.getEncoded();
返回原始;
}


私有静态字节[]加密(byte [] raw,byte [] clear)throws异常{
SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
密码密码= Cipher.getInstance(AES);
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
byte [] encrypted = cipher.doFinal(clear);
返回加密;
}

私有静态字节[] decrypt(byte [] raw,byte [] encrypted)throws异常{
SecretKeySpec skeySpec = new SecretKeySpec(raw,AES);
密码密码= Cipher.getInstance(AES);
cipher.init(Cipher.DECRYPT_MODE,skeySpec);
byte [] decryptpted = cipher.doFinal(encrypted);
返回解密;
}

public static String toHex(String txt){
return toHex(txt.getBytes());
}
public static String fromHex(String hex){
return new String(toByte(hex));
}

public static byte [] toByte(String hexString){
int len = hexString.length()/ 2;
byte [] result = new byte [len]; (int i = 0; i result [i] = Integer.valueOf(hexString.substring(2 * i,2 * i + 2),16).byteValue ();
返回结果;
}

public static String toHex(byte [] buf){
if(buf == null)
return;
StringBuffer result = new StringBuffer(2 * buf.length); (int i = 0; i< buf.length; i ++){
appendHex(result,buf [i]);

}
return result.toString();
}
private final static String HEX =0123456789ABCDEF;
private static void appendHex(StringBuffer sb,byte b){
sb.append(HEX.charAt((b>> 4)& 0x0f))。append(HEX.charAt(b& 0x0f ));
}

}


解决方案

如果您查看规范第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 +
'得到:(+ ciphertext.length()+)+ ciphertext);
System.out.println(解密它得到:+ plaintext2);
}
catch(Exception ex){
ex.printStackTrace();
}
}

哪些产生:


加密Hello world产生:(32)
5B68978D821FCA6022D4B90081F76B4F



解密它产生:Hello world



I use encryption AES algorithm, when i encrypt 16 byte(one block) the result is 32 byte. Is this ok?

My source code that i used is:

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)
 * </pre>
 * @author ferenc.hechler
 */
public class SimpleCrypto {

    public static String encrypt(String seed, String cleartext) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String seed, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }


    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }
    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length()/2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
        return result;
    }

    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2*buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }
    private final static String HEX = "0123456789ABCDEF";
    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
    }

}

解决方案

If you look at the specification section 5 then you can see that the input, output and state are all 128 bit. The only thing that varies is the size of the key: 128, 196 or 256 bits. So encrypting a 16 byte input state will yield a 16 byte output state.

Are you sure you aren't mixing it up with the length in hexadecimal notation or similar? If it is in hexadecimal notation then it's correct because for each byte two characters are needed to represent it: 00-FF (for the range 0-255).

Another way you can test if the encryption is correct is by doing the equivalent decryption, see if it matches the plaintext input string.

Anyway, it does the correct thing. Here's a test:

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();
  }
}

Which yields:

Encrypting 'Hello world' yields: (32) 5B68978D821FCA6022D4B90081F76B4F

Decrypting it yields: Hello world

这篇关于为什么使用AES加密16个字节时,密文32字节长?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆