JAR文件在Linux上按预期工作,在Windows上抛出异常

时间:2016-04-17 00:52:22

标签: java linux windows exception jar

我用Java编写了一个基本的文本加密程序。 (是的,我知道它使用的是ECB ......)

我的程序在Linux上正常运行。我将它作为JAR文件编译,并且在Linux上也可以正常工作。问题是,当我在Windows 上运行文件时,它会抛出异常,同时使用相同的密钥解密相同的文字 ,适用于Ubuntu。

我不知道从哪里开始调试,甚至不知道在Google上使用哪些搜索字词。我完全失去了。 我认为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");
        }
    }
}

1 个答案:

答案 0 :(得分:1)

由于Linux / Unix和Windows之间的CRLF存在差异,我在加密之前就看到了这一点。这两个操作系统完全不同地看到了回车换行和换行。

您可能需要使用Ant和fixcrlf步骤将代码编译到jar文件中:

DECLARE @StudentGrades TABLE(StudentId INT, ClassId INT, Grade DECIMAL(4,2))

-- Sample Entries:
INSERT INTO @StudentGrades
(StudentId, ClassId, Grade)
VALUES (1, 1, 60.0), (1, 2, 70.0), (2, 1, 75.0), (2, 2, 90.0);

-- Check table values.
SELECT * FROM @StudentGrades;

-- This is the report you were looking for.
SELECT StudentId, CONVERT(DECIMAL(4,1), AVG(Grade)) As [GPA]
FROM @StudentGrades
GROUP BY StudentId
ORDER BY GPA Desc; <---- EDITED BY FOXDONUT (GPA in descending order)

此外,它可能不是您的代码...如果您输入的文本没有正确的CRLF编码,您的加密也将失败。

编辑:

对于它的价值,下面是你的代码的删节版本,跳过操作...它只是接受密钥,然后加密然后转换并在一个流中解密所有...我厌倦了输入相同的操作,相同的键等...

无论如何,以下代码在没有BASE64编码器,解码器的情况下工作......我无法使用BASE64。尽管测试结果显示BASE64“似乎”正在工作,因为我在解码器之后得到了正确的加密文本,但它仍然继续抛出错误。

但是,如果你从图片中取出BASE64编码器和解码器,加密/解密工作正常...另外,我在那里添加了几个关键的.trim(),因为我看到在字符串中引入了隐形CRLF组件。

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

示例输出:

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

    }
}

最重要的是,BASE64编码器/解码器中有“某些东西”导致解密失败......它以某种方式改变了按位字符,这是我用System.out.println()看不到的。 ..也许十六进制输出可能会显示...