简体   繁体   English

AES / CFB / NOPADDING(128位),具有密码加盐功能

[英]AES/CFB/NOPADDING (128-bit) with password salting

I've tried running the code for about 3 days now but I am not able to figure out the mistake I've done. 我已经尝试运行了大约3天的代码,但是我无法弄清楚自己做错了什么。

I 'am using AES/CFB/NOPadding in 128 bit with password salting Salt_Len = 8 bytes and IV_Len = 16 bytes 我在128位中使用AES / CFB / NOPadding并带有密码盐化Salt_Len = 8 bytesIV_Len = 16 bytes

package Firstage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Random;
import java.util.Scanner;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class Thealgorithm1 
{

    static Scanner get = new Scanner(System.in);
    private static final String ALGORITHM = "AES";
    private static final String ALGORITHM_MODE ="AES/CFB/NoPadding";
    private static String password;

    public static void encrypt(File inputFile, File outputFile)
            throws Exception
    {
        System.out.println("Enetr passprhase");
        password=get.nextLine();

        final Random ivspc = new SecureRandom();
        byte[] ivspec = new byte[16];
        ivspc.nextBytes(ivspec);
        IvParameterSpec enciv = new IvParameterSpec(ivspec);

        FileOutputStream outputstrm = new FileOutputStream(outputFile);
        byte[] outputBytes = doCrypto(Cipher.ENCRYPT_MODE, inputFile,password,enciv);
        System.arraycopy(ivspec, 0,outputBytes , 0, 16);
        outputstrm.write(outputBytes);
        outputstrm.close();
        System.out.println("File encrypted successfully!");
    }

    public static void decrypt(File inputFile, File outputFile)
            throws Exception
    {

        System.out.println("Enter password");
        password=get.nextLine();
        IvParameterSpec hj = null;
        byte[]outpytBytes=doCrypto(Cipher.DECRYPT_MODE, inputFile,password,hj);
        FileOutputStream outputstrm = new FileOutputStream(outputFile);
        outputstrm.write(outpytBytes);
        outputstrm.close();
        System.out.println("File decrypted successfully!");
    }

    private static byte[] doCrypto(int cipherMode, File inputFile,String keyo ,IvParameterSpec ivespec)
            throws Exception {
    /* Derive the key, given password and salt. */
        final Random slt = new SecureRandom();
        byte[] salt = new byte[8];
        slt.nextBytes(salt);


        char[] passkeyo = keyo.toCharArray();
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(passkeyo, salt, 65536, 128);
        SecretKey tmp = factory.generateSecret(spec);

        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);

        FileInputStream fylin = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int)inputFile.length()];
        fylin.read(inputBytes);
        fylin.close();

        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE);

        byte[] outputBytes;
        if(cipherMode==2)
        {
            IvParameterSpec ivdec = new IvParameterSpec(inputBytes,0,16);
            cipher.init(cipherMode, secret,ivdec);
        }
        else
        {
            cipher.init(cipherMode, secret, ivespec);
        }


        if(cipherMode==2)
        {
            outputBytes = cipher.doFinal(inputBytes, 16,(inputBytes.length-16));
        }
        else
        {
            outputBytes=cipher.doFinal(inputBytes);
        }


        return outputBytes;

    }

    public static void main(String[] args)
    {

        File inputFile = new File("C:/temp/File.txt");
        File encryptedFile = new File("C:/temp/encryaes.enc");
        File decryptedFile = new File("C:/temp/mydr.txt");


        try {

            Thealgorithm1.encrypt(inputFile, encryptedFile);
            Thealgorithm1.decrypt(encryptedFile, decryptedFile);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }

}

The code encrypts it properly and also decrypts it, but the problem is that what it decrypts is not proper ie there's a fault in the code. 该代码对它进行了适当的加密和解密,但是问题在于它解密的内容不正确,即代码中存在错误。

You have two main issues in your code: 您的代码中有两个主要问题:

  1. The key must be exactly the same for encryption and decryption. 密钥对于加密和解密必须完全相同。 When you decrypt you are generating a different (random) salt value so, even if you enter the same passphrase, the decryption key is going to be different. 解密时,您将生成不同的(随机)盐值,因此,即使您输入相同的密码,解密密钥也将有所不同。 You can test this by making the salt a class attribute and only initializing it once. 您可以通过将salt作为类属性并仅对其初始化一次来进行测试。
  2. When you do this inside the encrypt method: 在crypto方法中执行此操作时:

     System.arraycopy(ivspec, 0,outputBytes , 0, 16); 

You are writing over the first 16 bytes of the encrypted output. 您正在写入加密输出的前16个字节。 My simple suggestion is to do something like this: 我的简单建议是执行以下操作:

byte[] outputBytes = doCrypto(Cipher.ENCRYPT_MODE, inputFile, password, enciv);
byte[] outputBytesWithIV = new byte[outputBytes.length + 16];
System.arraycopy(ivspec, 0, outputBytesWithIV, 0, 16);
System.arraycopy(outputBytes, 0, outputBytesWithIV, 16, outputBytes.length);
outputstrm.write(outputBytesWithIV);

You have two problems: 您有两个问题:

  • during encryption, you're overwriting a the first 16 bytes of the ciphertext with the IV. 在加密期间,您将用IV覆盖密文的前16个字节。 An easy fix is to write the IV to the stream instead of using System.arraycopy() . 一个简单的解决方法是将IV写入流中,而不是使用System.arraycopy() Change 更改

     System.arraycopy(ivspec, 0,outputBytes , 0, 16); 

    to

     outputstrm.write(ivspec); 
  • You're using a different salts during encryption and decryption, because you're always generating a new one. 在加密和解密期间,您使用的盐不同,因为您总是在生成新的盐。 You should also write the salt in front of the ciphertext beside the IV and read it back during decryption. 您还应该将盐写在IV旁边的密文前面,并在解密期间将其读回。
    You could also just use one of the two: generate a 16 byte salt and write that in front of the ciphertext. 您也可以只使用两者之一:生成一个16字节的盐,并将其写在密文前面。 Then you can use a static IV, because the semantic property is achieved from the random salt. 然后,您可以使用静态IV,因为语义属性是从随机盐中获得的。

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

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