AES算法的CBC模式加密(java实现,免费完整代码)

首先准备好两个文本文件(plain.txt和cipher.txt),这里我准备加密《荷塘月色》这篇文章。

 接下来是3个代码文件(AES.java,CBC.java,testCBC.java),一共5个文件放在同一目录下。接下来上代码:

AES.java如下:

package CBC;

public class AES {
    private byte[] key=null;
    private char[] ikey=null;
    private byte[] plaintext=null;
    private byte[] ciphertext= null;
    private static char Rcon[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
    private static char[] S= {
            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
    };
    private static char[] InvS= {
            0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
            0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
            0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
            0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
            0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
            0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
            0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
            0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
            0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
            0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
            0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
            0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
            0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
            0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
            0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
            0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
    };
    private static char x2time (char in)
    {
        char temp;
        temp = (char) (in<<1);
        if((in & 0x80)==0x80)
            temp ^= 0x1b;
        return (char) (temp&0xff);
    }
    private static char x3time(char in) {
        return (char) (x2time(in)^in);
    }
    private static char x9time(char in) {
        return (char) (x2time(x2time((char) x2time(in)))^in);
    }
    private static char xbtime(char in) {
        return (char) (x2time(x2time(x2time(in)))^x2time(in)^in);
    }
    private static char xdtime(char in) {
        return (char) (x2time(x2time(x2time(in)))^x2time(x2time(in))^in);
    }
    private static char xetime(char in) {
        return (char) (x2time(x2time(x2time(in)))^x2time(x2time(in))^x2time(in));
    }
    
    public AES(String key) {
        setKey(key);
        setPlaintext(new byte[0]);
        setCiphertext(new byte[0]);
    }
    public AES(byte[] key) {
        setKey(key);
        setPlaintext(new byte[0]);
        setCiphertext(new byte[0]);
    }
    public AES() {
        setKey(new byte[0]);
        setPlaintext(new byte[0]);
        setCiphertext(new byte[0]);
    }
    
    private void geneKey() {
        int i,j;
        this.ikey=new char[11*16];
        char[] T=new char[4];
        for(i=0;i<16;i++)
            this.ikey[i]=(char)(this.key[i]&0xff);
        for(i=4;i<44;i++) {
            if(i%4==0) {
                T[0]=(char) (S[this.ikey[4*i-3]]^Rcon[i/4-1]);
                T[1]=(char) (S[this.ikey[4*i-2]]);
                T[2]=(char) (S[this.ikey[4*i-1]]);
                T[3]=(char) (S[this.ikey[4*i-4]]);
                for(j=4*i;j<4*i+4;j++)
                    this.ikey[j]=(char) (this.ikey[j-16]^T[j%4]&0xff);
            }else {
                for(j=4*i;j<4*i+4;j++)
                    this.ikey[j]=(char) (this.ikey[j-16]^this.ikey[j-4]&0xff);
            }
        }
    }

    private byte[] EncryptRound(byte[] bin,int start) {
        byte[] out=new byte[16];
        char[] in=byteTochar(bin);
        out[0]=(byte) (x2time(S[in[0]])^x3time(S[in[5]])^S[in[10]]^S[in[15]]^this.ikey[start]);
        out[1]=(byte) (x2time(S[in[1]])^x3time(S[in[6]])^S[in[11]]^S[in[12]]^this.ikey[start+1]);
        out[2]=(byte) (x2time(S[in[2]])^x3time(S[in[7]])^S[in[8]]^S[in[13]]^this.ikey[start+2]);
        out[3]=(byte) (x2time(S[in[3]])^x3time(S[in[4]])^S[in[9]]^S[in[14]]^this.ikey[start+3]);
        
        out[4]=(byte) (S[in[0]]^x2time(S[in[5]])^x3time(S[in[10]])^S[in[15]]^this.ikey[start+4]);
        out[5]=(byte) (S[in[1]]^x2time(S[in[6]])^x3time(S[in[11]])^S[in[12]]^this.ikey[start+5]);
        out[6]=(byte) (S[in[2]]^x2time(S[in[7]])^x3time(S[in[8]])^S[in[13]]^this.ikey[start+6]);
        out[7]=(byte) (S[in[3]]^x2time(S[in[4]])^x3time(S[in[9]])^S[in[14]]^this.ikey[start+7]);
        
        out[8]=(byte) (S[in[0]]^S[in[5]]^x2time(S[in[10]])^x3time(S[in[15]])^this.ikey[start+8]);
        out[9]=(byte) (S[in[1]]^S[in[6]]^x2time(S[in[11]])^x3time(S[in[12]])^this.ikey[start+9]);
        out[10]=(byte) (S[in[2]]^S[in[7]]^x2time(S[in[8]])^x3time(S[in[13]])^this.ikey[start+10]);
        out[11]=(byte) (S[in[3]]^S[in[4]]^x2time(S[in[9]])^x3time(S[in[14]])^this.ikey[start+11]);
        
        out[12]=(byte) (x3time(S[in[0]])^S[in[5]]^S[in[10]]^x2time(S[in[15]])^this.ikey[start+12]);
        out[13]=(byte) (x3time(S[in[1]])^S[in[6]]^S[in[11]]^x2time(S[in[12]])^this.ikey[start+13]);
        out[14]=(byte) (x3time(S[in[2]])^S[in[7]]^S[in[8]]^x2time(S[in[13]])^this.ikey[start+14]);
        out[15]=(byte) (x3time(S[in[3]])^S[in[4]]^S[in[9]]^x2time(S[in[14]])^this.ikey[start+15]);
        return out;
    }
    
    private byte[] EncryptLastRound(byte[] bin) {
        char[] in=byteTochar(bin);
        byte[] out=new byte[16];
        out[0]=(byte) (S[in[0]]^this.ikey[160]);
        out[1]=(byte) (S[in[1]]^this.ikey[161]);
        out[2]=(byte) (S[in[2]]^this.ikey[162]);
        out[3]=(byte) (S[in[3]]^this.ikey[163]);
        
        out[4]=(byte) (S[in[5]]^this.ikey[164]);
        out[5]=(byte) (S[in[6]]^this.ikey[165]);
        out[6]=(byte) (S[in[7]]^this.ikey[166]);
        out[7]=(byte) (S[in[4]]^this.ikey[167]);
        
        out[8]=(byte) (S[in[10]]^this.ikey[168]);
        out[9]=(byte) (S[in[11]]^this.ikey[169]);
        out[10]=(byte) (S[in[8]]^this.ikey[170]);
        out[11]=(byte) (S[in[9]]^this.ikey[171]);
        
        out[12]=(byte) (S[in[15]]^this.ikey[172]);
        out[13]=(byte) (S[in[12]]^this.ikey[173]);
        out[14]=(byte) (S[in[13]]^this.ikey[174]);
        out[15]=(byte) (S[in[14]]^this.ikey[175]);
        return out;
    }
    
    private byte[] DecryptRound(byte[] in,int start) {
        
        char[] lineTran=byteTochar(DecryptLastRound(in,start));
        byte[] output=new byte[16];
        output[0]=(byte) (xetime(lineTran[0])^xbtime(lineTran[4])^xdtime(lineTran[8])^x9time(lineTran[12]));
        output[1]=(byte) (xetime(lineTran[1])^xbtime(lineTran[5])^xdtime(lineTran[9])^x9time(lineTran[13]));
        output[2]=(byte) (xetime(lineTran[2])^xbtime(lineTran[6])^xdtime(lineTran[10])^x9time(lineTran[14]));
        output[3]=(byte) (xetime(lineTran[3])^xbtime(lineTran[7])^xdtime(lineTran[11])^x9time(lineTran[15]));
        
        output[4]=(byte) (x9time(lineTran[0])^xetime(lineTran[4])^xbtime(lineTran[8])^xdtime(lineTran[12]));
        output[5]=(byte) (x9time(lineTran[1])^xetime(lineTran[5])^xbtime(lineTran[9])^xdtime(lineTran[13]));
        output[6]=(byte) (x9time(lineTran[2])^xetime(lineTran[6])^xbtime(lineTran[10])^xdtime(lineTran[14]));
        output[7]=(byte) (x9time(lineTran[3])^xetime(lineTran[7])^xbtime(lineTran[11])^xdtime(lineTran[15]));
        
        output[8]=(byte) (xdtime(lineTran[0])^x9time(lineTran[4])^xetime(lineTran[8])^xbtime(lineTran[12]));
        output[9]=(byte) (xdtime(lineTran[1])^x9time(lineTran[5])^xetime(lineTran[9])^xbtime(lineTran[13]));
        output[10]=(byte) (xdtime(lineTran[2])^x9time(lineTran[6])^xetime(lineTran[10])^xbtime(lineTran[14]));
        output[11]=(byte) (xdtime(lineTran[3])^x9time(lineTran[7])^xetime(lineTran[11])^xbtime(lineTran[15]));
        
        output[12]=(byte) (xbtime(lineTran[0])^xdtime(lineTran[4])^x9time(lineTran[8])^xetime(lineTran[12]));
        output[13]=(byte) (xbtime(lineTran[1])^xdtime(lineTran[5])^x9time(lineTran[9])^xetime(lineTran[13]));
        output[14]=(byte) (xbtime(lineTran[2])^xdtime(lineTran[6])^x9time(lineTran[10])^xetime(lineTran[14]));
        output[15]=(byte) (xbtime(lineTran[3])^xdtime(lineTran[7])^x9time(lineTran[11])^xetime(lineTran[15]));
        
        return output;
    }
    private byte[] DecryptLastRound(byte[] bin,int start) {
        char[] in=byteTochar(bin);
        byte[] lineTran=new byte[16];
        lineTran[0]=(byte) (InvS[in[0]]^this.ikey[start]);
        lineTran[1]=(byte) (InvS[in[1]]^this.ikey[start+1]);
        lineTran[2]=(byte) (InvS[in[2]]^this.ikey[start+2]);
        lineTran[3]=(byte) (InvS[in[3]]^this.ikey[start+3]);
        
        lineTran[4]=(byte) (InvS[in[7]]^this.ikey[start+4]);
        lineTran[5]=(byte) (InvS[in[4]]^this.ikey[start+5]);
        lineTran[6]=(byte) (InvS[in[5]]^this.ikey[start+6]);
        lineTran[7]=(byte) (InvS[in[6]]^this.ikey[start+7]);
        
        lineTran[8]=(byte) (InvS[in[10]]^this.ikey[start+8]);
        lineTran[9]=(byte) (InvS[in[11]]^this.ikey[start+9]);
        lineTran[10]=(byte) (InvS[in[8]]^this.ikey[start+10]);
        lineTran[11]=(byte) (InvS[in[9]]^this.ikey[start+11]);
        
        lineTran[12]=(byte) (InvS[in[13]]^this.ikey[start+12]);
        lineTran[13]=(byte) (InvS[in[14]]^this.ikey[start+13]);
        lineTran[14]=(byte) (InvS[in[15]]^this.ikey[start+14]);
        lineTran[15]=(byte) (InvS[in[12]]^this.ikey[start+15]);
        
        return lineTran;
    }
    public void Encrypt() {
        byte[] inout=new byte[16];
        for(int i=0;i<16;i++)
            inout[i]=(byte) (this.plaintext[i]^this.ikey[i]);
        for(int j=0;j<9;j++)
            inout=EncryptRound(inout,16*j+16);
        this.ciphertext=EncryptLastRound(inout);
    }
    public void Decrypt() {
        byte[] inout=new byte[16];
        for(int i=0;i<16;i++)
            inout[i]=(byte) (this.ciphertext[i]^this.ikey[i+160]);
        for(int j=0;j<9;j++)
            inout=DecryptRound(inout,(9-j)*16);
        this.plaintext=DecryptLastRound(inout,0);
    }
    
    public void Encrypt(String plaintext) {
        setPlaintext(plaintext);
        Encrypt();
    }
    public void Encrypt(byte[] plaintext) {
        setPlaintext(plaintext);
        Encrypt();
    }
    public void Decrypt(String ciphertext) {
        setCiphertext(ciphertext);
        Decrypt();
    }
    public void Decrypt(byte[] ciphertext) {
        setCiphertext(ciphertext);
        Decrypt();
    }
    public void showIkey() {
        int i,j;
        for(i=0;i<44;i++) {
            if(i%4==0)System.out.print(String.format("k%d:    ",i/4));
            for(j=4*i;j<4*i+4;j++)
                System.out.print(String.format("%02x ",this.ikey[j]));
            if(i%4==3)System.out.println();
        }
    }
    public void showInfo() {
        showKey();
        showIkey();
        showPlaintext();
        showCiphertext();
    }
    public void showKey() {
        int i;
        System.out.print("Key:\n  Hex:");
        for(i=0;i<16;i++)
            System.out.print(String.format("%02x ",this.key[i]));
        System.out.print("\n  CH:");
        String strKey=new String(this.key);
        System.out.println(strKey);
    }
    public void showPlaintext() {
        int i;
        System.out.print("Plaintext:\n  Hex:");
        for(i=0;i<16;i++)
            System.out.print(String.format("%02x ",this.plaintext[i]));
        System.out.print("\n  CH:");
        String strPlaintext=new String(this.plaintext);
        System.out.println(strPlaintext);
    }
    public void showCiphertext() {
        int i;
        System.out.print("Ciphertext:\n  Hex:");
        for(i=0;i<16;i++)
            System.out.print(String.format("%02x ",this.ciphertext[i]));
        System.out.println();
    }
    public void setKey(byte[] key) {
        this.key=new byte[16];
        int n=key.length>16?16:key.length;
        for(int i=0;i<n;i++)
            this.key[i] = key[i];
        geneKey();
    }
    public void setKey(String key) {
        setKey(key.getBytes());
    }
    public byte[] getPlaintext() {
        return this.plaintext;
    }
    public void setPlaintext(byte[] plaintext) {
        this.plaintext=new byte[16];
        int n=plaintext.length>16?16:plaintext.length;
        for(int i=0;i<n;i++)
            this.plaintext[i] = plaintext[i];
    }
    public void setPlaintext(String plaintext) {
        setPlaintext(plaintext.getBytes());
    }
    public byte[] getCiphertext() {
        return this.ciphertext;
    }
    public void setCiphertext(byte[] ciphertext) {
        this.ciphertext=new byte[16];
        int n=ciphertext.length>16?16:ciphertext.length;
        for(int i=0;i<n;i++)
            this.ciphertext[i] = ciphertext[i];
    }
    public void setCiphertext(String ciphertext) {
        setCiphertext(ciphertext.getBytes());
    }
    public char[] byteTochar(byte[] byteArray) {
        char[] charArray=new char[byteArray.length];
        for(int i=0;i<byteArray.length;i++)
            charArray[i]=(char) (byteArray[i]&0xff);
        return charArray;
    }
}

CBC.java如下:

package CBC;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class CBC {
    private byte[] plaintext=null;
    private byte[] ciphertext=null;
    private byte[] IV=new byte[16];
    AES aes=new AES();
    public CBC() {
        IV=new byte[0];
    }
    public CBC(byte[] key) {
        aes.setKey(key);
    }
    public CBC(byte[] key,byte[] IV) {
        aes.setKey(key);
        int n=IV.length>16?16:IV.length;
        for(int i=0;i<n;i++)
            this.IV[i]=IV[i];
    }
    public CBC(String key) {
        aes.setKey(key);
        this.IV=new byte[16];
    }
    public CBC(String key,String IV) {
        aes.setKey(key);
        byte[] iv=IV.getBytes();
        int n=iv.length>16?16:iv.length;
        for(int i=0;i<n;i++)
            this.IV[i]=iv[i];
    }
    
    public void Encrypt() {
        this.ciphertext=new byte[0];
        if(this.plaintext.length==0) {
            System.out.println("No Ciphertext!");
            return;
        }
        byte[] input=null;
        if(this.plaintext.length<=16) {
            input=byteXOR(this.IV, this.plaintext);
            aes.Encrypt(input);
            this.ciphertext=aes.getCiphertext();
            return;
        }
        int i,plainLength,plainBlockNumber,lastBlockLength;
        byte[] lastCipher=null;
        plainLength=this.plaintext.length;
        plainBlockNumber=plainLength/16;
        lastBlockLength=plainLength%16;
        lastCipher=this.IV;
        for(i=0;i<plainBlockNumber;i++) {
            input=byteXOR(lastCipher, subByte(this.plaintext,16*i,16*i+16));
            aes.Encrypt(input);
            lastCipher=aes.getCiphertext();
            this.ciphertext=byteAdd(this.ciphertext, lastCipher);
        }
        if(lastBlockLength==0)return;
        byte[] plainLastBlock=subByte(this.plaintext,16*plainBlockNumber);
        byte[] LastBlock=byteAdd(plainLastBlock,subByte(lastCipher,lastBlockLength));
        LastBlock=byteXOR(LastBlock, subByte(lastCipher,0,lastBlockLength));
        aes.Encrypt(LastBlock);
        LastBlock=byteAdd(aes.getCiphertext(),subByte(lastCipher,0,lastBlockLength));
        this.ciphertext=byteAdd(subByte(this.ciphertext,0,16*plainBlockNumber-16),LastBlock);
    }
    public void Decrypt() {
        this.plaintext=new byte[0];
        if(this.ciphertext.length==0) {
            System.out.println("No Plaintext!");
            return;
        }
        if(this.ciphertext.length<=16) {
            aes.Decrypt(this.ciphertext);
            this.plaintext=byteXOR(this.IV,aes.getPlaintext());
            return;
        }
        byte[] lastCipher=null;
        int i,cipherLength,cipherBlockNumber,lastBlockLength;
        cipherLength=this.ciphertext.length;
        cipherBlockNumber=cipherLength/16;
        lastBlockLength=cipherLength%16;
        lastCipher=this.IV;
        for(i=0;i<cipherBlockNumber-1;i++) {
            aes.Decrypt(subByte(this.ciphertext,16*i,16*i+16));
            this.plaintext=byteAdd(this.plaintext,byteXOR(lastCipher,aes.getPlaintext()));
            lastCipher=subByte(this.ciphertext,16*i,16*i+16);
        }
        if(lastBlockLength==0) {
            aes.Decrypt(subByte(this.ciphertext,16*cipherBlockNumber-16,16*cipherBlockNumber));
            this.plaintext=byteAdd(this.plaintext,byteXOR(lastCipher,aes.getPlaintext()));
            return;
        }
        byte[] lastBlockCipher=subByte(this.ciphertext,16*cipherBlockNumber-16,16*cipherBlockNumber);
        byte[] lastSmallCipher=subByte(this.ciphertext,16*cipherBlockNumber);
        aes.Decrypt(lastBlockCipher);
        byte[] lastPlain=aes.getPlaintext();
        byte[] lastSmallPlain=subByte(byteXOR(lastPlain, lastSmallCipher),0,lastBlockLength);
        lastBlockCipher=byteAdd(lastSmallCipher,subByte(lastPlain,lastBlockLength));
        aes.Decrypt(lastBlockCipher);
        lastPlain=byteXOR(aes.getPlaintext(),lastCipher);
        lastPlain=byteAdd(lastPlain,lastSmallPlain);
        this.plaintext=byteAdd(subByte(this.plaintext,0,16*cipherBlockNumber-16),lastPlain);
    }
    
    public void setIV(byte[] IV) {
        int n=IV.length>16?16:IV.length;
        for(int i=0;i<n;i++)
            this.IV[i]=IV[i];
    }
    public void setIV(String IV) {
        byte[] iv=IV.getBytes();
        int n=iv.length>16?16:iv.length;
        for(int i=0;i<n;i++)
            this.IV[i]=iv[i];
    }
    public void setKey(byte[] Key) {
        aes.setKey(Key);
    }
    public void setKey(String Key) {
        aes.setKey(Key);
    }
    
    public byte[] getPlaintext() {
        return this.plaintext;
    }
    public void setPlaintext(byte[] plaintext) {
        this.plaintext = plaintext;
    }
    public void setPlaintext(String plainPath) {
        StringBuilder sb=new StringBuilder();
        try {
            BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(plainPath),"UTF-8"));
            String str;
            while((str=br.readLine())!=null)
                sb.append(str+"\n");
            sb.deleteCharAt(sb.length()-1);
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
        this.plaintext=sb.toString().getBytes();
    }
    public byte[] getCiphertext() {
        return this.ciphertext;
    }
    public void setCiphertext(byte[] ciphertext) {
        this.ciphertext = ciphertext;
    }
    public void setCiphertext(String cipherPath) {
        StringBuilder sb=new StringBuilder();
        try {
            BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(cipherPath)));
            String str;
            while((str=br.readLine())!=null)
                sb.append(str+"\n");
            sb.deleteCharAt(sb.length()-1);
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
        this.ciphertext=stringTobyte(sb.toString());
    }
    public void writePlaintext(String plainPath) {
        try {
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(plainPath),"UTF-8"));
            bw.write(new String(this.plaintext));
            bw.flush();
            bw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void writeCiphertext(String cipherPath) {
        try {
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(cipherPath),"UTF-8"));
            bw.write(byteToString(this.ciphertext));
            bw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void showInfo() {
        showKey();
        showPlaintext();
        showCiphertext();
    }
    public void showKey() {
        aes.showKey();
    }
    public void showIkey() {
        aes.showIkey();
    }
    public void showPlaintext() {
        String hexString = "0123456789abcdef";
        System.out.print("Plaintext:\n  Hex:");
        StringBuilder sb = new StringBuilder(this.plaintext.length * 2);
        for (int i = 1; i <= this.plaintext.length; i++) {
            sb.append(hexString.charAt((this.plaintext[i-1] & 0xf0) >> 4));
            sb.append(hexString.charAt((this.plaintext[i-1] & 0x0f) >> 0));
            if(i%80==0)sb.append("\n");
        }
        System.out.println(sb.toString());
        System.out.println("  CH:"+new String(this.plaintext));
    }
    public void showCiphertext() {
        String hexString = "0123456789abcdef";
        System.out.print("Ciphertext:\n  Hex:");
        StringBuilder sb = new StringBuilder(this.ciphertext.length * 2);
        for (int i = 1; i <= this.ciphertext.length; i++) {
            sb.append(hexString.charAt((this.ciphertext[i-1] & 0xf0) >> 4));
            sb.append(hexString.charAt((this.ciphertext[i-1] & 0x0f) >> 0));
            if(i%80==0)sb.append("\n");
        }
        System.out.println(sb.toString());
    }
    private byte[] byteAdd(byte[] bt1, byte[] bt2){
        byte[] bt3 = new byte[bt1.length+bt2.length];  
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);  
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);  
        return bt3;  
    }
    private byte[]  byteXOR(byte[] bt1, byte[] bt2) {
        byte[] bt3 = new byte[16];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        for(int i=0;i<bt2.length;i++)
            bt3[i]^=bt2[i];
        return bt3;
    }
    private byte[] subByte(byte[] bt,int start) {
        byte[] re=new byte[bt.length-start];
        for(int i=0;i<re.length;i++)
            re[i]=bt[i+start];
        return re;
    }
    private byte[] subByte(byte[] bt,int start,int end) {
        byte[] re=new byte[end-start];
        for(int i=0;i<re.length;i++)
            re[i]=bt[i+start];
        return re;
    }
    private String byteToString(byte[] bt){
        String hexString = "0123456789abcdef";
        String str="";
        for(byte b:bt) {
            str+=hexString.charAt(b>>4&0xf);
            str+=hexString.charAt(b&0xf);
        }
        return str;
    }
    private byte[] stringTobyte(String str){
        int high,low;
        byte[] buf=new byte[str.length()/2];
        for(int i=0;i<str.length()/2;i++) {
            high=Integer.parseInt(str.substring(i*2, i*2+1),16);
            low=Integer.parseInt(str.substring(i*2+1, i*2+2),16);
            buf[i]=(byte)(high*16+low);
        }
        return buf;
    }
}

testCBC.java如下:

package CBC;

public class testCBC {
    static String plainPath="src/CBC/plain.txt";
    static String cipherPath="src/CBC/cipher.txt";
    public static void main(String[] args) {
        String key="fhieowubgjdkjldfl";
        String IV="fwsssssrf45";
        CBC cbc=new CBC(key,IV);
        //测试加密
        encrypt(cbc, plainPath);
        //测试解密
//        decrypt(cbc, cipherPath);
    }
    public static void encrypt(CBC cbc,String plainPath) {
        cbc.setPlaintext(plainPath);
        cbc.Encrypt();
        cbc.writeCiphertext(cipherPath);
        cbc.showPlaintext();
        cbc.showCiphertext();
    }
    public static void decrypt(CBC cbc,String cipherPath) {
        cbc.setCiphertext(cipherPath);
        cbc.Decrypt();
        cbc.writePlaintext(plainPath);
        cbc.showPlaintext();
        cbc.showCiphertext();
    }
}

测试结果:

可以看到加密后的密文(16进制)已经保存在了cipher.txt中:

接下来注释掉第11行,第13行取消注释,进行解密的测试:

 文章被正确的解密!

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

实无所得

随缘打赏吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值