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.

  • 相关阅读:
    linux读写锁
    轻量级过程改进之需求开发
    Hibernate4.3.6 Final+Spring3.0.5配置出错提示及解决方法
    hdu1198Farm Irrigation(dfs找联通)
    ushare编译之 ‘struct sockaddr_storage’ has no member named ‘s_addr’
    iOS的URLScheme
    Python学习笔记(一)
    un-资源-开源-WebGallery:Windows Web App Gallery
    几何-莱罗三角形:百科
    几何-正十七边形:百科
  • 原文地址:https://www.cnblogs.com/xunbu7/p/6934361.html
Copyright © 2011-2022 走看看