如何仅将文本加密为纯文本字符串

时间:2017-01-16 08:38:45

标签: java encryption

我必须在我的程序中实现基本加密。我可以使用Base64它被客户拒绝了。所以我使用以下方法。我面临的问题是加密中有特殊字符会导致异常。我可以更改此代码以某种方式加密成纯文本而无需特殊字符。

protected static byte[] encrypt(String text) 
    {
        try
        {
            String key = "6589745268754125";
            // 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(text.getBytes());
            return encrypted;
        }
        catch(Exception ex)
        {
            WriteLog("Encryption Failed");
            WriteLog(ex.getMessage());
            return null;
        }
    }

protected static String decrypt(byte[] pass)
{
    try
    {
        String key = "6589745268754125";
        // Create key and cipher
        Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        // decrypt the text
        cipher.init(Cipher.DECRYPT_MODE, aesKey);           
        String decrypted = new String(cipher.doFinal(pass));        
        return decrypted;
    }
    catch(Exception ex)
    {
        WriteLog("Encryption Failed");      
        WriteLog(ex.getMessage());
        return null;
    }
}

异常消息显示“给定最终块未正确填充” javax.crypto.BadPaddingException:给定最终块未正确填充

4 个答案:

答案 0 :(得分:1)

如果客户端不喜欢Base64,请尝试Base32或Base16(= hex)。它们不常见但是定义为Base64的替代品。

您可能还会找到客户端不希望您使用Base64的确切原因。

答案 1 :(得分:1)

所以,基本上你不了解加密并且遇到客户想要加密的问题

好的,快速抬头:

编码:将输入转换为输出,该输出保存相同的信息但在另一种表示中...例如:1,2,3 - > A,B,C

正如您所看到的那样,输出看起来不同,但保留了相同的信息

请注意,编码/解码不需要任何秘密信息

加密:乍一看可能看起来很相似,但在这里你需要一些秘密...加密需要2个输入...一个秘密和输入数据

结果输出可以解密,但只有你有相应的秘密

如果您的客户希望您加密某些内容,请确保该内容可以表示为字节...加密字符串...不好...加密已转换为<在这里插入任意字节编码,例如unicode> ......好的

加密通常处理字节(让我们不关心历史密码)

当您决定使用加密/密码时,您必须知道基本上有2个不同的组:symetric和asymetric

symetric:解密需要用于加密的相同密钥(读取密钥)

不对称:密钥对由公共部分和私有部分(公钥/私钥)组成,公共部分用于加密,私有部分用于解密...除非你有不同的方需要,否则没有意义交换钥匙

不对称密码通常用于加密解密对称密码的密钥,因为它们是SLOW而对称密码通常是快速的

不对称密码不用于加密大量数据

symetric密码适用于批量数据

如果您的目标只是在硬盘上放置信息时加密信息,那么您可以使用对称密码

你需要一个密钥才能使密码运行......并且......你将有问题在哪里存储...所以如果可以,让用户输入一个足够复杂的密码...使用密码和一个名为PBKDF2的函数具有足够高的迭代次数(足够高=增加此数字,直到该过程需要几秒钟,如果您在启动时只需要这个,或者直到您的用户开始抱怨延迟)才能生成二进制密钥密码。

在GCM模式下使用此密钥进行AES(对称密码)

密码将需要一个名为IV或初始化向量的东西......

iv并不是秘密,你可以将这个东西作为明文信息添加到你的密文中 iv需要是密码的一个块的大小,因此在AES 128位= 16字节的情况下 所以加密时你的IV是一个16字节(唯一)的随机数(意味着你可能不会使用IV两次或更多次:坚持使用过的IV,当得到一个新的时,检查它是否已经存储,如果是,则启动IV生成,如果没有,存储它然后使用它)

解密时,从文件中读取前置的明文IV(前16个字节)

如果您只想将密文存储在磁盘上,请将其写入二进制文件

如果文件必须只包含可打印文本,则在将字节写入文件之前应用base16 / 32/64之类的编码,并在解密前解码为字节数组(除非您的数据太大,否则您将拥有查找/编写将为您添加/剥离编码的流包装器

答案 2 :(得分:0)

你应该Base64加密的内容。顺便说一句,这是通常的技术。

我猜客户端的问题不是Base64格式本身,而是事实上,Base64不是(强大的)加密。

答案 3 :(得分:0)

问题是填充。我使用AES/CBC/NoPadding并确保我的字符串是16个字节的倍数。所以除了改变ecryption和解密之外我还要添加两种方法。一个是将\0,即隐式空终止符添加到文本的结尾,使其成为16的倍数,另一个是在解密后删除它们。所以最终版本是这样的。

public class crypto {

    static String IV = "AAAAAAAAAAAAAAAA";
    static String plaintext = "my non padded text";
    static String encryptionKey = "0123456789abcdef";

    public static void main(String[] args) 
    {
        byte[] cipher = encrypt(plaintext);
        String decrypted = decrypt(cipher);
    }

    protected static String covertto16Byte(String plainText)
    {
        while(plainText.length()%16 != 0)
            plainText += "\0";          
        return plainText;
    }

    protected static String removePadding(String plainText)
    {
        return plainText.replace("\0","");
    }

    protected static byte[] encrypt(String plainText) 
    {
        try 
        {
            String _plaintText_16 = covertto16Byte(plainText);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
            SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
            return cipher.doFinal(_plaintText_16.getBytes("UTF-8"));
        } catch (Exception ex) 
        {
            //catch mechanism
            return null;
        }
    }

    protected static String decrypt(byte[] cipherText) 
    {
        try 
        {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
            SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
            return removePadding(new String(cipher.doFinal(cipherText), "UTF-8"));
        } catch (Exception ex) 
        {   
            //catch mechanism
            return null;
        }
    }    
}