zoukankan      html  css  js  c++  java
  • AES encryption of files (and strings) in java with randomization of IV (initialization vector)

    http://siberean.livejournal.com/14788.html

    Java encryption-decryption examples, I've seen so far in Internet, are having IV been hard coded, i.e. not changed every time. However randomization of the initialization vector (IV) is a must for AES and for strong security (WEP was compromised because of hardcoding of IV). Notice that IV is not a "salt", and is not a secret, but like a cryptographic nonce - must be randomized each time.
    In simple example below - IV is attached in the beginning of the stream.

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.File;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.security.SecureRandom;
    import java.util.Arrays;
    
    import javax.crypto.Cipher;
    import javax.crypto.CipherInputStream;
    import javax.crypto.CipherOutputStream;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    
    public class Encryption {
    
        private static final int IV_LENGTH=16;
    
        /* A helper - to reuse the stream code below - if a small String is to be encrypted */
        public static byte[] encrypt(String plainText, String password) throws Exception {
            ByteArrayInputStream bis = new ByteArrayInputStream(plainText.getBytes("UTF8"));
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            encrypt(bis, bos, password);
            return bos.toByteArray();
        }
    
    
        public static byte[] decrypt(String cipherText, String password) throws Exception {
            byte[] cipherTextBytes = cipherText.getBytes();
            ByteArrayInputStream bis = new ByteArrayInputStream(cipherTextBytes);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            decrypt(bis, bos, password);        
            return bos.toByteArray();
        }
    
    
        public static void encrypt(InputStream in, OutputStream out, String password) throws Exception{
    
            SecureRandom r = new SecureRandom();
            byte[] iv = new byte[IV_LENGTH];
            r.nextBytes(iv);
            out.write(iv); //write IV as a prefix
            out.flush();
            //System.out.println(">>>>>>>>written"+Arrays.toString(iv));
    
            Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); //"DES/ECB/PKCS5Padding";"AES/CBC/PKCS5Padding"
            SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);        
    
            out = new CipherOutputStream(out, cipher);
            byte[] buf = new byte[1024];
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
    
    
        public static void decrypt(InputStream in, OutputStream out, String password) throws Exception{
    
            byte[] iv = new byte[IV_LENGTH];
            in.read(iv);
            //System.out.println(">>>>>>>>red"+Arrays.toString(iv));
    
            Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); //"DES/ECB/PKCS5Padding";"AES/CBC/PKCS5Padding"
            SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    
            in = new CipherInputStream(in, cipher);
            byte[] buf = new byte[1024];
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
    
    
        public static void copy(int mode, String inputFile, String outputFile, String password) throws Exception {
    
            BufferedInputStream is = new BufferedInputStream(new FileInputStream(inputFile));
            BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
            if(mode==Cipher.ENCRYPT_MODE){
                encrypt(is, os, password);
            }
            else if(mode==Cipher.DECRYPT_MODE){
                decrypt(is, os, password);
            }
            else throw new Exception("unknown mode");
            is.close();
            os.close();
        }
    
    
        public static void main(String[] args){
    
            if(args.length<1){
                System.out.println("Pass at least one argument (filename)");        
                return;
            }
            try{
                //check files - just for safety
                String fileName=args[0];
                String tempFileName=fileName+".enc";
                String resultFileName=fileName+".dec";
    
                File file = new File(fileName);
                if(!file.exists()){
                    System.out.println("No file "+fileName);
                    return;
                }
                File file2 = new File(tempFileName);
                File file3 = new File(resultFileName);
                if(file2.exists() || file3.exists()){
                    System.out.println("File for encrypted temp file or for the result decrypted file already exists. Please remove it or use a different file name");
                    return;
                }
    
                copy(Cipher.ENCRYPT_MODE, fileName, tempFileName, "password12345678");
                copy(Cipher.DECRYPT_MODE, tempFileName, resultFileName, "password12345678");
    
                System.out.println("Success. Find encrypted and decripted files in current directory");
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }    
    
    }

    Usage:

    $ javac Encryption.java

    Pass any existing file, you want to encrypt through command line argument (test.sh in the following example):

    $ java Encryption test.sh
    Success. Find encrypted and decripted files in current directory

    Encrypted file (test.enc):

    $ cat test.sh.enc
    &X▒b▒▒▒▒_▒▒$Z▒▒f▒XboM▒  ▒_f§R▒s▒♣▒▒K▒M;▒▒▒▒'L▒ZS◄;▒▒i
    ▒▒|VØ▒:?▒▒▒?▒9y{7"▒▒▒▒+▒▒e}▒▒yi▒▒y_/jjU:▒▒_▒ ►p▒?▒▒▒;[lE▒▒▒▒Cpc▒46▒▒▒▒@▒<▒n▒↓I▒
    ▒▒s▒?b▒p▒O▒▒▒▒▒▒▒d▒4n3'▒▒▒Y♦<▒▒▒▒▒▒>▒▒▒▒Ih▒▒▒´▒↓_R▒vGW▒▒▒V▒▒?(Q♥G     J◄DMS▒▒▒
    zC;*

    Let's check the decrypted file (test.dec):

    $ cat test.sh.dec
    #!/bin/sh
    
    i=0
    depth=6
    
    nodes_number=$(echo "2^$depth" | bc)
    
    #echo "total nodes: $nodes_number"
    
    while [ $i -lt $nodes_number ] ;do
    
            number=$(echo "obase=2;$i" | bc)
            printf "%0${depth}o
    " 0$number
            i=`expr $i + 1`
    done

    The file is readable.

  • 相关阅读:
    032 Gradle 下载的依赖jar包在哪?
    031 can't rename root module,Android Studio修改项目名称
    030 Cannot resolve symbol'R' 问题解决汇总大全
    029 Android Studio层级显示目录文件
    028 You are about to commit CRLF line separators to the Git repository.It is recommended to set the core. autocrlf Git attribute to true to avoid line separator issues If you choose Fix and Comit ,
    027 【Android基础知识】Android Studio 编译慢及 Adb connection Error:远程主机强迫关闭了一个现有的连接
    026 Android Studio 和Gradle版版本对应关系
    025 Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm
    024 Android Studio上传项目到Github 最全记录
    023 解决AndroidStudio下载gradle慢的问题
  • 原文地址:https://www.cnblogs.com/xunbu7/p/6934361.html
Copyright © 2011-2022 走看看