【问题标题】:Cannot decrypt cyphertext from text file, symmetric key implement. in java无法从文本文件中解密密文,对称密钥实现。在java中
【发布时间】:2009-12-16 23:27:47
【问题描述】:

所以基本上我的程序从用户选择的文本文件中加密/解密字符串。 他可以选择五种算法之一。问题是当我用例如创建密文时。 AES 然后将此密文保存到文本文件并想对其进行解密以获取它不起作用的原始字符串。谁能指出问题出在哪里?

例如:如果我使用 AES 加密字符串:“Hello World !!”我得到这个密文:“1za7slAXv2KZvDlVZlzu/A==”然后我将它保存到 .txt 并使用第二种方式进行解密以获得“Hello World !!”背部。但结果很糟糕。

我的方法好吗?有没有更好的办法?

忘记添加导入: 并且很抱歉之前的格式。

import java.io.*;
import java.util.Scanner;

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

import java.security.spec.KeySpec;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.PBEKeySpec;

import javax.crypto.BadPaddingException;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.io.UnsupportedEncodingException;


public class sifrovaniRaw  {

Cipher sifr, desifr;



sifrovaniRaw(SecretKey klic, String algoritmus)
{
    try {
        sifr = Cipher.getInstance(algoritmus); 
        desifr = Cipher.getInstance(algoritmus);
        sifr.init(Cipher.ENCRYPT_MODE, klic);  
        desifr.init(Cipher.DECRYPT_MODE, klic);

    }
    catch (NoSuchPaddingException e) {
        System.out.println(" NoSuchPaddingException");
    }
    catch (NoSuchAlgorithmException e) {
        System.out.println(" NoSuchAlgorithmException");
    }
    catch (InvalidKeyException e) {
        System.out.println(" InvalidKeyException");
    }
}



sifrovaniRaw(String passph) {

    byte[] sul =
    {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99

    };


    int iterace = 20;

    try {

        KeySpec klicSpecifikace = new PBEKeySpec(passph.toCharArray(), sul, iterace);
        SecretKey klic = SecretKeyFactory.getInstance("PBEWithMD5AndTripleDES").generateSecret(klicSpecifikace);

        sifr = Cipher.getInstance(klic.getAlgorithm());
        desifr = Cipher.getInstance(klic.getAlgorithm());


        AlgorithmParameterSpec parametry = new PBEParameterSpec(sul, iterace);

        sifr.init(Cipher.ENCRYPT_MODE, klic, parametry);
        desifr.init(Cipher.DECRYPT_MODE, klic, parametry);
    }
    catch (InvalidAlgorithmParameterException e) {
        System.out.println(" InvalidAlgorithmParameterException");
    }
    catch (InvalidKeySpecException e) {
        System.out.println(" InvalidKeySpecException");
    }
    catch (NoSuchPaddingException e) {
        System.out.println(" NoSuchPaddingException");
    }
    catch (NoSuchAlgorithmException e) {
        System.out.println(" NoSuchAlgorithmException");
    }
    catch (InvalidKeyException e) {
        System.out.println(" InvalidKeyException");
    }
}


public String encryption(String str) {
    try {

        byte[] utf8 = str.getBytes("UTF8");


        byte[] enco = sifr.doFinal(utf8);


        return new sun.misc.BASE64Encoder().encode(enco);

    } catch (BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (IOException e) {
    }
    return null;
}



public String decryption(String str) {

    try {


        byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
        byte[] utf8 = desifr.doFinal(dec);


        return new String(utf8, "UTF8");

    } catch (BadPaddingException e) {
    } catch (IllegalBlockSizeException e) {
    } catch (UnsupportedEncodingException e) {
    } catch (IOException e) {
    }
    return null;
}





public static void testsecklic()
{


      System.out.println("Testing method using secret key");
      System.out.println("");

      try {
          System.out.println("Give a path:");
          System.out.println("-----");
          System.out.println("for UNIX eg: \"/home/user/text_to_encrypt/decrypt.txt\"");
          System.out.println("for NT Windows eg: \"C://FileIO//text.txt\"");
          System.out.println("------");
            Scanner scan = new Scanner(System.in);
            String filepath = scan.next();
            File file = new File(filepath);
            BufferedInputStream bin = null;

            FileInputStream fin = new FileInputStream(file);
            bin = new BufferedInputStream(fin);
            byte[] contents = new byte[1024];
            int bytesRead=0;
            String StringCont;

            while( (bytesRead = bin.read(contents)) != -1)
            {
                StringCont = new String(contents, 0, bytesRead);
                System.out.print(StringCont);


        SecretKey aesKlic    = KeyGenerator.getInstance("AES").generateKey();
        SecretKey desKlic       = KeyGenerator.getInstance("DES").generateKey();
        SecretKey desedeKlic    = KeyGenerator.getInstance("DESede").generateKey();
        SecretKey rc2Klic    = KeyGenerator.getInstance("RC2").generateKey();
        SecretKey blowfishKlic  = KeyGenerator.getInstance("Blowfish").generateKey();

        StringEncrypter aesEncrypt = new StringEncrypter(aesKlic, aesKlic.getAlgorithm());
        StringEncrypter desEncrypt = new StringEncrypter(desKlic, desKlic.getAlgorithm());
        StringEncrypter desedeEncrypt = new StringEncrypter(desedeKlic, desedeKlic.getAlgorithm());
        StringEncrypter rc2Encrypt = new StringEncrypter(rc2Klic, rc2Klic.getAlgorithm());
        StringEncrypter blowfishEncrypt = new StringEncrypter(blowfishKlic, blowfishKlic.getAlgorithm());


        String aesEncrypted       = aesEncrypt.encrypt(StringCont);
        String desEncrypted       = desEncrypt.encrypt(StringCont);
        String rc2Encrypted       = desedeEncrypt.encrypt(StringCont);
        String desedeEncrypted    = rc2Encrypt.encrypt(StringCont);
        String blowfishEncrypted  = blowfishEncrypt.encrypt(StringCont);


        String aesDecrypt       = aesEncrypt.decrypt(aesEncrypted);
        String desDecrypt       = desEncrypt.decrypt(desEncrypted);
        String rc2Decrypt       = rc2Encrypt.decrypt(desedeEncrypted);
        String desedeDecrypt    = desedeEncrypt.decrypt(rc2Encrypted);
        String blowfishDecrypt  = blowfishEncrypt.decrypt(blowfishEncrypted);



        //FIRST NON-WORKING WAY of decrypting.
        System.out.println("Do you want to encrypt[1] or decrypt[2] text ?");
        int sifDesif = scan.nextInt();

        if(sifDesif == 1)
        {
            System.out.println("What cypher do you want to choose?");
            System.out.println("AES[1], DES[2], rc2[3], blowfish[4], desede[5]");
            int vyber = scan.nextInt();

            switch(vyber)
            {
                case 1: System.out.println("encrypted : " + aesEncrypted); break;
                case 2: System.out.println("encrypted : " + desEncrypted); break;
                case 3: System.out.println("encrypted : " + rc2Encrypted); break;
                case 4: System.out.println("encrypted : " + blowfishEncrypted); break;
                case 5: System.out.println("encrypted : " + desedeEncrypted); break;
            }

        }
        else if(sifDesif == 2)
        {
            System.out.println("What cypher do you want to choose?");
            System.out.println("AES[1], DES[2], rc2[3], blowfish[4], desede[5]");
            int vyber = scan.nextInt();

            switch(vyber)
            {
                case 1:System.out.println("decrypted : " + aesDecrypt); break;
                case 2:System.out.println("decrypted : " + desDecrypt); break;
                case 3:System.out.println("decrypted : " + rc2Decrypt); break;
                case 4:System.out.println("decrypted : " + blowfishDecrypt); break;
                case 5:System.out.println("decrypted : " + desedeDecrypt); break;
            }
        }
        //SECOND WORKING WAY of decrypting.
        System.out.println("Algorith used:" + aesKlic.getAlgorithm());
        System.out.println("text  : " + StringCont);
        System.out.println("encryption : " + aesEncrypted);
        System.out.println("decryption text : " + aesDecrypt);
        System.out.println();



       }
    }
    catch (NoSuchAlgorithmException e)
    {
        System.out.println(" No such Algo");
    }
        catch(FileNotFoundException e)
    {
        System.out.println("File not found" + e);
    }
    catch(IOException ioe)
    {
        System.out.println("Exception while reading the file "+ ioe);
    }
}


public static void main(String[] args)
{
    testsecklic();
}

}

【问题讨论】:

    标签: java encryption


    【解决方案1】:

    由于您每次都在生成加密密钥,因此程序将无法解密使用不同加密密钥创建的密文。如果您想在程序运行之间重复使用加密密钥,您需要找到一种方法来保存它。

    以下程序是原始示例的较小版本,不同之处在于它使用每个密码对明文进行加密和解密。我无法访问StringEncrypter 类,所以我写了一个简单的版本:

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    
    public class EncTest {
    
        public static void main(String[] args) throws Exception {
            System.out.println("Testing method using secret key");
    
            String plaintext = "hello world";
    
            SecretKey aesKlic = KeyGenerator.getInstance("AES").generateKey();
            SecretKey desKlic = KeyGenerator.getInstance("DES").generateKey();
            SecretKey desedeKlic = KeyGenerator.getInstance("DESede").generateKey();
            SecretKey rc2Klic = KeyGenerator.getInstance("RC2").generateKey();
            SecretKey blowfishKlic = KeyGenerator.getInstance("Blowfish").generateKey();
    
            StringEncrypter[] ciphers = new StringEncrypter[] {
                new StringEncrypter(aesKlic, aesKlic.getAlgorithm()), 
                new StringEncrypter(desKlic, desKlic.getAlgorithm()), 
                new StringEncrypter(desedeKlic, desedeKlic.getAlgorithm()), 
                new StringEncrypter(rc2Klic, rc2Klic.getAlgorithm()), 
                new StringEncrypter(blowfishKlic, blowfishKlic.getAlgorithm())
            };
    
            byte[][] ciphertexts = new byte[ciphers.length][];
    
            int i = 0;
            for (StringEncrypter cipher : ciphers) {
                ciphertexts[i] = cipher.encrypt(plaintext);
                System.out.println(cipher.getAlgorithm() + " encrypted: " + hexEncode(ciphertexts[i]));
                i++;
            }
    
            System.out.println();
    
            i = 0;
            for (StringEncrypter cipher : ciphers) {
                System.out.println(cipher.getAlgorithm() + " decrypted: " + cipher.decrypt(ciphertexts[i]));
                i++;
            }
        }
    
        // Hex encoding lifted from commons-codec
    
        private static String hexEncode(byte [] input) {
            return new String(encodeHex(input));
        }
    
        private static char[] encodeHex(byte[] data) {
    
            int l = data.length;
    
               char[] out = new char[l << 1];
    
               // two characters form the hex value.
               for (int i = 0, j = 0; i < l; i++) {
                   out[j++] = DIGITS[(0xF0 & data[i]) >>> 4 ];
                   out[j++] = DIGITS[ 0x0F & data[i] ];
               }
    
               return out;
        }
    
        private static final char[] DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7',
               '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
        };
    
        private static class StringEncrypter {
    
            private final SecretKey key;
            private final String algorithm;
    
            public StringEncrypter(SecretKey key, String algorithm) {
                this.key = key;
                this.algorithm = algorithm;
            }
    
            public String getAlgorithm() {
                return algorithm;
            }
    
            public byte[] encrypt(String input) throws Exception {
                Cipher cipher = Cipher.getInstance(algorithm);
                cipher.init(Cipher.ENCRYPT_MODE, key);
    
                return cipher.doFinal(input.getBytes("UTF-8"));
            }
    
            public String decrypt(byte[] input) throws Exception {
                Cipher cipher = Cipher.getInstance(algorithm);
                cipher.init(Cipher.DECRYPT_MODE, key);
    
                return new String(cipher.doFinal(input));
            }
    
        }
    }
    

    【讨论】:

    • 感谢您的回答。我只是没有意识到我总是得到新密钥:) 但是当我打印出密钥时,我得到了类似“javax.crypto.spec.SecretKeySpec@1708d;”的东西并且可能无法使用它。我真的需要能够存储/恢复密钥,但不知道如何。我有一些想法,但它看起来可能很糟糕。你能提供一些例子吗?
    • 您可以使用 SecretKey#getEncoded() 获取原始密钥材料。然后,您可以对其进行 hex/base64 编码并将其存储在某处。但是,如果您没有办法正确存储您的密钥材料,这是非常不安全的。我建议改用适当的 PBE 密码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 2021-02-02
    • 2016-09-28
    相关资源
    最近更新 更多