简体   繁体   English

JAR 文件在 Linux 上按预期工作,在 Windows 上引发异常

[英]JAR file works as expected on Linux, throws exceptions on Windows

I have written a basic text encryption program in Java.我用 Java 编写了一个基本的文本加密程序。 (Yes, I'm aware that it uses ECB...) (是的,我知道它使用欧洲央行......)

My program works fine on Linux.我的程序在 Linux 上运行良好。 I complied it as a JAR file, and that also works fine on Linux.我将它编译为JAR文件,这在 Linux 上也能正常工作。 The problem is that when I run the file on Windows , it will throw an exception while decrypting the same text with the same key that worked on Ubuntu.问题是,当我在 Windows 上运行该文件,它会在使用在 Ubuntu 上工作的相同密钥解密相同文本抛出异常

I have no idea where to start debugging or even what search terms to use on Google.我不知道从哪里开始调试,甚至不知道在 Google 上使用什么搜索词。 I am at a complete loss.我完全不知所措。 I thought Java was cross-platform.我认为 Java 是跨平台的。

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

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

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

public class Application
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        String textToEncrypt = "Hello World";
        String textToDecrypt;
        String textToDecryptAscii;
        String result;
        int operation;
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");
        } catch (NoSuchAlgorithmException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (NoSuchPaddingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        //String key = "Bar12345Bar12345"; // 128 bit key
        String key = null;

        BASE64Encoder asciiEncoder = new BASE64Encoder();
        BASE64Decoder asciiDecoder = new BASE64Decoder();

        System.out.printf("Enter:\n1 for encryption\n2 for decryption\n\nChoice: ");
        operation = input.nextInt();
        input.nextLine();

        if (operation == 1)
        {
            try 
            {
                System.out.print("Enter a 128-bit key to be used for encryption: ");
                key = input.nextLine();

                if(key.length() != 16)
                {
                    while(key.length() != 16)
                    {
                        System.out.print("You need to enter a *128-bit* key: ");
                        key = input.nextLine();
                    }
                }

                System.out.printf("\n---------\n\nText to encrypt: ");
                textToEncrypt = input.nextLine();

                //Create key and cipher
                Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
                //Cipher cipher = Cipher.getInstance("AES");

                //encrypt the text
                cipher.init(Cipher.ENCRYPT_MODE, aesKey);
                byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes());

                StringBuilder sb = new StringBuilder();
                for (byte b: encrypted)
                {
                    sb.append((char)b);
                }

                // the encrypted String
                String enc = sb.toString();
                //System.out.println("encrypted:" + enc);

                String asciiEncodedEncryptedResult = asciiEncoder.encodeBuffer(enc.getBytes());

                asciiEncodedEncryptedResult = asciiEncodedEncryptedResult.replace("\n", "").replace("\r", "");

                System.out.println("Encrypted text: " + asciiEncodedEncryptedResult);
                //System.out.printf("\n------------------------------\nDecrypted text: " + asciiEncodedEncryptedResult + "\n------------------------------\n\n\n");

            }
            catch(Exception e) 
            {
                e.printStackTrace();
            }
        }
        else if (operation == 2)
        {
            System.out.printf("\n---------\n\nText to decrypt: ");
            textToDecryptAscii = input.nextLine();

            System.out.print("Enter the 128-bit decryption key: ");
            key = input.nextLine();

            if(key.length() != 16)
            {
                while(key.length() != 16)
                {
                    System.out.print("You need to enter a *128-bit* key: ");
                    key = input.nextLine();
                }
            }

            byte[] decodedBytes = null;
            try
            {
                decodedBytes = asciiDecoder.decodeBuffer(textToDecryptAscii);
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            //System.out.println("decodedBytes " + new String(decodedBytes));

            textToDecrypt = new String(decodedBytes);

            //Convert the string to byte array
            //for decryption
            byte[] bb = new byte[textToDecrypt.length()];
            for (int i=0; i<textToDecrypt.length(); i++)
            {
                bb[i] = (byte) textToDecrypt.charAt(i);
            }

            //decrypt the text
            Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
            try
            {
                cipher.init(Cipher.DECRYPT_MODE, aesKey);
            }
            catch (InvalidKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String decrypted = null;
            try
            {
                decrypted = new String(cipher.doFinal(bb));
            }
            catch (IllegalBlockSizeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (BadPaddingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.printf("\n------------------------------\nDecrypted text: " + decrypted + "\n------------------------------\n\n\n");
        }
    }
}

I've seen this before doing encryption because of the differences in CRLF between Linux/Unix and Windows.由于 Linux/Unix 和 Windows 之间 CRLF 的差异,我在进行加密之前已经看到了这一点。 The two operating systems see Carriage Return Line Feed and Line Feed quite differently.这两个操作系统对回车换行和换行的看法截然不同。

You may need to compile your code into a jar file using Ant and the fixcrlf step :您可能需要使用 Ant 和 fixcrlf 步骤将代码编译成 jar 文件:

    <fixcrlf 
        srcdir="${dir.prj.work}"
        eol="dos"
        includes="**/*"
    />

Also, it may not be your code...If the text your are feeding in doesn't have the correct CRLF encoded, your encryption will fail as well.此外,它可能不是您的代码...如果您输入的文本没有正确的 CRLF 编码,您的加密也会失败。

Edit :编辑 :

For what it's worth, below is an abridged version of your code, that skips operations...it just takes in the key, does the encryption then turns around and decrypts all in one stream...I got tired of inputting the same operations, same keys, etc...值得一提的是,下面是您代码的删节版,它跳过了操作……它只需要输入密钥,然后加密然后在一个流中翻转并解密所有内容……我厌倦了输入相同的操作,相同的键,等等...

Anyway, the following code works without the BASE64 Encoder, Decoder...I couldn't get it to work with the BASE64.无论如何,下面的代码在没有 BASE64 编码器、解码器的情况下工作......我无法让它与 BASE64 一起工作。 Although output from tests showed the BASE64 "seemed" to be working as I was getting what looked like the correct encrypted text after the Decoder, but it still continued to throw the error.虽然测试的输出显示 BASE64“似乎”正在工作,因为我在解码器之后得到了看起来像正确的加密文本,但它仍然继续抛出错误。

However, if you take the BASE64 Encoder and Decoder out of the picture, the encryption/decryption works fine...Also, I added a few key .trim() in there as I saw invisible CRLF being introduced in the String components.但是,如果您将 BASE64 编码器和解码器从图片中取出,则加密/解密工作正常……此外,我在其中添加了一些密钥 .trim(),因为我看到在 String 组件中引入了不可见的 CRLF。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;

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

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;

public class Application { 

    public Application() {
        // TODO Auto-generated constructor stub
    }

    public static void main ( String[] args ) {
        Scanner input = new Scanner(System.in);
        String textToEncrypt = "Hello World";
        String textToDecrypt;
        String textToDecryptAscii;
        String result;
        int operation;
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        } catch (NoSuchPaddingException e1) {
            e1.printStackTrace();
        }

        //String key = "Bar12345Bar12345"; // 128 bit key
        String key = null;
        //byte[] key = null;

        //BASE64Encoder asciiEncoder = new BASE64Encoder();
        //BASE64Decoder asciiDecoder = new BASE64Decoder();

        //System.out.printf("Enter:\n1 for encryption\n2 for decryption\n\nChoice: ");
        //operation = input.nextInt();
        //input.nextLine();

        try { 
            System.out.print("Enter a 128-bit key to be used for encryption: ");
            key = input.nextLine();

            if ( key.length() != 16 ) {
                while ( key.length() != 16 ) {
                    System.out.print("You need to enter a *128-bit* key: ");
                    key = input.nextLine();
                }
            }
            System.out.println ( "128-bit encryption key.......................["+key+"] length ["+key.length ()+"]");

            System.out.printf ( "Text to encrypt..............................[");
            //System.out.printf("\n---------\n\nText to encrypt: ");
            textToEncrypt = input.nextLine();
            System.out.println ( "Text to encrypt..............................["+textToEncrypt+"] length ["+textToEncrypt.length ()+"]");

            //Create key and cipher
            Key aesKey = new SecretKeySpec(key.trim().getBytes(), "AES");
            //Cipher cipher = Cipher.getInstance("AES");

            //encrypt the text
            cipher.init(Cipher.ENCRYPT_MODE, aesKey);
            byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes ());

            StringBuilder sb = new StringBuilder();
            for (byte b: encrypted) {
                sb.append((char)b);
            }

            // the encrypted String
            String enc = sb.toString();
            System.out.println ( "Encrypted text...............................["+enc+"] length ["+enc.length ()+"]");
            //System.out.println("encrypted:" + enc);

            //String asciiEncodedEncryptedResult = asciiEncoder.encodeBuffer(enc.getBytes()).trim ();
            String asciiEncodedEncryptedResult = enc.trim ();
            System.out.println ( "Encoded text.................................["+asciiEncodedEncryptedResult+"] length ["+asciiEncodedEncryptedResult.length ()+"]");

            //asciiEncodedEncryptedResult = asciiEncodedEncryptedResult.replace("\n", "").replace("\r", "");
            asciiEncodedEncryptedResult = asciiEncodedEncryptedResult.trim ();

            System.out.println ( "Encrypted text...............................["+asciiEncodedEncryptedResult+"] length ["+asciiEncodedEncryptedResult.length ()+"]");


            //byte[] decodedBytes = null;
            //try {
            //    decodedBytes = asciiDecoder.decodeBuffer(asciiEncodedEncryptedResult);
            //} 
            //catch (IOException e1) {
            //    e1.printStackTrace();
            //}
            //System.out.println ( "Decoded Bytes................................["+decodedBytes+"] length ["+decodedBytes.length+"]");

            //textToDecrypt = new String(decodedBytes);
            textToDecrypt = asciiEncodedEncryptedResult;

            System.out.println ( "Text to Decrypt..............................["+textToDecrypt+"] length ["+textToDecrypt.length()+"]");

            //Convert the string to byte array
            //for decryption
            byte[] bb = new byte[textToDecrypt.length()];
            for ( int i=0; i<textToDecrypt.length(); i++ ) {
                bb[i] = (byte) textToDecrypt.charAt(i);
            }

            //decrypt the text
            //Key aesKey = null;
            String decrypted = null;
            try {
                //aesKey = new SecretKeySpec(key.trim ().getBytes (), "AES");
                cipher.init(Cipher.DECRYPT_MODE, aesKey);
                decrypted = new String(cipher.doFinal(bb));
            }
            catch (InvalidKeyException e) {
                e.printStackTrace();
            }
            catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            }
            catch (BadPaddingException e) {
                e.printStackTrace();
            }
            catch ( Exception ltheXcp ) { 
                ltheXcp.printStackTrace ();
            }

            if ( decrypted != null ) {
                System.out.println ( "Decrypted text...............................["+decrypted+"] length ["+decrypted.length ()+"]");
            }
            else { 
                System.out.println ( "Decrypted text...............................["+decrypted+"] length []");
            }

        }
        catch ( Exception ltheXcp ) { 
            ltheXcp.printStackTrace ();
        }

    }
}

Sample output :示例输出:

Enter a 128-bit key to be used for encryption: aaaaaaaaaaaaaaaa
128-bit encryption key.......................[aaaaaaaaaaaaaaaa] length [16]
Text to encrypt..............................[adymlincoln
Text to encrypt..............................[adymlincoln] length [11]
Encrypted text...............................[\_i8`???R????] length [16]
Encoded text.................................[\_i8`???R????] length [16]
Encrypted text...............................[\_i8`???R????] length [16]
Text to Decrypt..............................[\_i8`???R????] length [16]
Decrypted text...............................[adymlincoln] length [11]

Bottom line, there is "something" in the BASE64 Encoder/Decoder that is causing the decryption to fail...It's changing the bitwise characters in some fashion that I couldn't see using System.out.println()...perhaps a Hexidecimal output might show what...最重要的是,BASE64 编码器/解码器中有“某些东西”导致解密失败......它正在以某种方式更改按位字符,而我使用 System.out.println() 无法看到......也许十六进制输出可能会显示什么......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM