AES解密与弹性城堡 [英] AES decryption with bouncy castle

查看:250
本文介绍了AES解密与弹性城堡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试在 http://www.java2s .com / Code / Java / Security / Basicsymmetricencryptionexample.htm 必须使用3个参数,模式(加密或解密),IV和密钥进行调用。它还读取和写入特定文件。



到目前为止,我忽略了给定的IV和键,直到我休息并运行。我的代码成功地从文件加密明文,并将密文写入文件,但解密不工作。看来,解密模式读取的字节比加密写的多,我得到块对齐错误。



我确定在解密部分的某处有一些根本性的错误,但我不知道是什么。



错误发生在


$

b $ b

  try {ctLength + = cipher.doFinal(cipherText,ctLength);} catch {IllegalBlockSizeException e)

代码行:

  import java.io.BufferedWriter; 
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;



@SuppressWarnings(unused)
public class AESCTR {
static String inputFile =plain-in.txt;
static String outputFile =cipher-out.txt;
static String cInputFile =cipher-in.txt;
static String cOutputFile =plain-out.txt;
static String mode;
static String IV;
static String key;
public static void main(String [] args){
if(Security.getProvider(BC)== null){
System.out.println(Bouncy Castle provider is NOT可用);
System.exit(-1);
}
else {
System.out.println(Bouncy Castle提供程序可用);
}
Security.addProvider(Security.getProvider(BC));
// TODO自动生成的方法stub
if(args.length!= 3){
System.out.println(Invalid number of arguments\\\
);
System.exit(-1);
}
mode = args [0];
IV = args [1];
key = args [2];
if((!mode.equals(enc))&&(!mode.equals(dec))){
System.out.println(Invalid mode \\\
);
System.exit(-1);
}
byte [] keyBytes = new byte [] {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d ,0x0e,0x0f};
System.out.println(keyBytes.length);
SecretKeySpec key = new SecretKeySpec(keyBytes,AES);
System.out.println(Mode:+ mode +IV:+ IV +Key:+ key);
if(mode.equals(enc)){
intctLength = 0;
byte [] data = null;
try {
路径path = Paths.get(inputFile);
dat = Files.readAllBytes(path);
} catch(IOException e){
// TODO自动生成的catch块
e.printStackTrace();
System.out.println(Invalid Path \\\
);
System.exit(-1);
}
while((data.length%16)!= 0){//填充
byte [] dest = new byte [data.length + 1];
byte [] pad = new byte [] {0x00};
System.arraycopy(data,0,dest,0,data.length);
System.arraycopy(pad,0,dest,data.length,pad.length);
data = dest;
}
System.out.println(data.length);
byte [] cipherText = new byte [data.length];

Cipher cipher = null;
try {
cipher = Cipher.getInstance(AES / ECB / NoPadding,BC);
} catch(NoSuchAlgorithmException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(NoSuchProviderException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(NoSuchPaddingException e){
// TODO自动生成的catch块
e.printStackTrace();
}
System.out.println(input text:+ new String(data));

try {
cipher.init(Cipher.ENCRYPT_MODE,key);
} catch(InvalidKeyException e){
// TODO自动生成的catch块
e.printStackTrace();
}
try {
ctLength = cipher.update(data,0,data.length,cipherText,0);
} catch(ShortBufferException e){
// TODO自动生成的catch块
e.printStackTrace();
}
try {
ctLength + = cipher.doFinal(cipherText,ctLength);
} catch(IllegalBlockSizeException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(ShortBufferException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(BadPaddingException e){
// TODO自动生成的catch块
e.printStackTrace();
}
Writer writer = null;
try {writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cInputFile),utf-8));
writer.write(new String(cipherText));
} catch(IOException ex){
System.out.println(File Write Error\ n);
System.exit(-1);
} finally {
try {writer.close();} catch(Exception ex){}
}

byte [] c = null;
try {
路径path = Paths.get(cInputFile);
c = Files.readAllBytes(path);
} catch(IOException e){
// TODO自动生成的catch块
e.printStackTrace();
System.out.println(Invalid Path \\\
);
System.exit(-1);
}
System.out.println(cipher text:+ new String(c)+bytes:+ ctLength);
}
else if(mode.equals(dec)){
byte [] c = null;
try {
路径path = Paths.get(cInputFile);
c = Files.readAllBytes(path);
File f = new File(cInputFile);
System.out.println(In Bytes:+ c.length);
} catch(IOException e){
// TODO自动生成的catch块
e.printStackTrace();
System.out.println(Invalid Path \\\
);
System.exit(-1);
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance(AES / ECB / NoPadding,BC);
} catch(NoSuchAlgorithmException e1){
// TODO自动生成的catch块
e1.printStackTrace();
} catch(NoSuchProviderException e1){
// TODO自动生成catch块
e1.printStackTrace();
} catch(NoSuchPaddingException e1){
// TODO自动生成的catch块
e1.printStackTrace();
}
byte [] plainText = new byte [c.length];
try {
cipher.init(Cipher.DECRYPT_MODE,key);
} catch(InvalidKeyException e){
// TODO自动生成的catch块
e.printStackTrace();
}
int ptLength = 0;
try {
ptLength = cipher.update(c,0,c.length,plainText,0);
System.out.println(ptLength);
} catch(ShortBufferException e){
// TODO自动生成的catch块
e.printStackTrace();
}
try {
ptLength + = cipher.doFinal(plainText,ptLength);
} catch(IllegalBlockSizeException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(ShortBufferException e){
// TODO自动生成的catch块
e.printStackTrace();
} catch(BadPaddingException e){
// TODO自动生成的catch块
e.printStackTrace();
}
System.out.println(plain text:+ new String(plainText)+bytes:+ ptLength);
}
}
}


解决方案>

您尝试将大量随机字节解码为UTF-8编码文本。这不会工作。您的密文破坏,因为任何不形成字符的有效UTF-8编码的字节序列将替换为替换字符0 + FFFD(�)。



密码文本实际上不是文本。不要使用与文本一起使用的 Writer Reader 等API。使用类似于 OutputStream InputStream 的工作于字节数组的API。



如果您需要将密文存储为文本,请使用二进制到文本编码(如Base64)对其进行编码。



具体来说,密码文本包含以下内容:

  try {
Files.write(Paths.get(cInputFile),cipherText );
} catch(IOException ex){
System.out.println(File Write Error);
System.exit(-1);
}


I am attempting to adapt the sample code at http://www.java2s.com/Code/Java/Security/Basicsymmetricencryptionexample.htm to have to be invoked with 3 arguments, the mode (encryption or decryption), IV and the key. It also reads and writes to specific files.

As of right now I am ignoring the given IV and key until I get the rest up and running. My code successfully encrypts plaintext from a file, and writes the ciphertext to a file, but the decryption does not work. It appears that decryption mode reads in more bytes than encryption wrote and I get block alignment errors.

I'm sure there is some fundamental error somewhere in the decryption section but I do not know what it is. If anyone can identify the issue or can see any blatant errors that may cause it please let me know.

The error occurs at the

try{ ctLength += cipher.doFinal(cipherText, ctLength);}catch{IllegalBlockSizeException e)

line of code in:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;



@SuppressWarnings("unused")
public class AESCTR {
    static String inputFile = "plain-in.txt";
    static String outputFile = "cipher-out.txt";
    static String cInputFile = "cipher-in.txt";
    static String cOutputFile = "plain-out.txt";
    static String mode;
    static String IV;
    static String key;
    public static void main(String[] args) {
        if (Security.getProvider("BC") == null){
            System.out.println("Bouncy Castle provider is NOT available");
            System.exit(-1);
        }
        else{
            System.out.println("Bouncy Castle provider is available");
        } 
        Security.addProvider(Security.getProvider("BC")); 
        // TODO Auto-generated method stub
        if (args.length != 3){
            System.out.println("Invalid number of arguments\n");
            System.exit(-1);
        }
        mode = args[0];
        IV = args[1];
        key = args[2];
        if ((!mode.equals("enc")) && (!mode.equals("dec"))){
            System.out.println("Invalid mode\n");
            System.exit(-1);
        }
        byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
        System.out.println(keyBytes.length);
        SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
        System.out.println("Mode: " + mode + " IV: " + IV + " Key: " + key);
        if(mode.equals("enc")){
            int ctLength = 0;
            byte[] data = null;
            try {
                Path path = Paths.get(inputFile);
                data = Files.readAllBytes(path);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("Invalid Path\n");
                System.exit(-1);
             }
            while((data.length % 16) != 0){ //Padding
                byte[] dest = new byte[data.length + 1];
                byte[] pad = new byte[] {0x00};
                System.arraycopy(data, 0, dest, 0, data.length);
                System.arraycopy(pad, 0, dest, data.length, pad.length);    
                data = dest;
            }
            System.out.println(data.length);
            byte[] cipherText = new byte[data.length];

            Cipher cipher = null;
            try {
                cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC");
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchProviderException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("input text : " + new String(data));

            try {
                cipher.init(Cipher.ENCRYPT_MODE, key);
            } catch (InvalidKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                ctLength = cipher.update(data, 0, data.length, cipherText, 0);    
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                ctLength += cipher.doFinal(cipherText, ctLength);
            } catch (IllegalBlockSizeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BadPaddingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Writer writer = null;
            try{ writer = new BufferedWriter(new OutputStreamWriter(new     FileOutputStream(cInputFile), "utf-8"));
            writer.write(new String(cipherText));
            } catch (IOException ex){
                System.out.println("File Write Error\n");
                System.exit(-1);
            } finally{
                try{writer.close();}catch (Exception ex){}
            }

            byte[] c = null;
            try {
                Path path = Paths.get(cInputFile);
                c = Files.readAllBytes(path);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("Invalid Path\n");
                System.exit(-1);
            }
            System.out.println("cipher text: " + new String(c) + " bytes: " + ctLength);
        }
        else if (mode.equals("dec")){
            byte[] c = null;
            try {
                Path path = Paths.get(cInputFile);
                c = Files.readAllBytes(path);
                File f = new File(cInputFile);
                System.out.println("In Bytes: " + c.length);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("Invalid Path\n");
                System.exit(-1);
            }
            Cipher cipher = null;
            try {
                cipher = Cipher.getInstance("AES/ECB/NoPadding", "BC");
            } catch (NoSuchAlgorithmException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (NoSuchProviderException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (NoSuchPaddingException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            byte[] plainText = new byte[c.length];
            try {
                cipher.init(Cipher.DECRYPT_MODE, key);
            } catch (InvalidKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            int ptLength = 0;
            try {
                ptLength = cipher.update(c, 0, c.length, plainText, 0);
                System.out.println(ptLength);
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                ptLength += cipher.doFinal(plainText, ptLength);
            } catch (IllegalBlockSizeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ShortBufferException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BadPaddingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("plain text : " + new String(plainText) + " bytes: " + ptLength);
        }
    }
}

解决方案

You are attempting to decode a lot of random bytes as UTF-8 encoded text. That won't work. Your cipher text becomes corrupted, because any byte sequences that don't form a valid UTF-8 encoding of a character will be replaced with the replacement character, 0+FFFD (�).

Cipher text is not actually text. Don't use APIs like Writer and Reader that work with text. Use APIs like OutputStream and InputStream that work with byte arrays.

If you need to store the cipher text as text, encode it with a binary-to-text encoding like Base64.

Specifically, you should replace your write of the cipher text with something like this:

try {
  Files.write(Paths.get(cInputFile), cipherText);
} catch (IOException ex) {
  System.out.println("File Write Error");
  System.exit(-1);
}

这篇关于AES解密与弹性城堡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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