【前端Js】高级加密解密标准AES加密(Javascript代码实现)

来源:互联网 发布:windowsphone软件格式 编辑:程序博客网 时间:2024/06/07 05:55


高级加密标准(Advanced Encryption Standard,AES)

是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。Rijndael加密算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之,投稿高级加密标准的甄选流程。(Rijdael的发音近于 "Rhinedoll"。)

 

AES的区块长度固定为128比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度均可以是128,192或256比特。

AES加密有很多轮的重复和变换。大致步骤如下:

1、密钥扩展(KeyExpansion),

2、初始轮(Initial Round),

3、重复9轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,

4、最终轮(Final Round),最终轮没有MixColumns。

 

4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。

1 字节代替

  字节代替的主要功能是通过S盒完成一个字节到另外一个字节的映射。

2 行移位

  行移位的功能是实现一个4x4矩阵内部字节之间的置换。

3 列混淆

  列混淆:利用GF(2^8)域上算术特性的一个代替。

4 轮密码加

  这个操作相对简单,其依据的原理是“任何数和自身的异或结果为0”。加密过程中,每轮的输入与每轮密钥异或一次;因此,解密时再异或上该轮的密钥即可恢复输入。

5 密钥扩展

密钥扩展过程说明:

    1)  将初始密钥以列为主,转化为4个32 bits的字,分别记为w[0…3];

    2)  按照如下方式,依次求解w[j],其中j是整数并且属于[4,43];

    3)  若j%4=0,则w[j]=w[j-4]⊕g(w[j-1]),否则w[j]=w[j-4]⊕w[j-1];

  函数g的流程说明:

    4)  将w循环左移一个字节;

    5)  分别对每个字节按S盒进行映射;

    6)  与32 bits的常量(RC[j/4],0,0,0)进行异或,RC是一个一维数组,其值如下。(RC的值只需要有10个,而此处用了11个,实际上RC[0]在运算中没有用到,增加RC[0]是为了便于程序中用数组表示。由于j的最小取值是4,j/4的最小取值则是1,因此不会产生错误。)

      RC = {00, 01, 02, 04, 08, 10, 20, 40, 80, 1B, 36}

Js核心代码:

// inverse process column infofunction InvMixColumns(state){   var col;   var c0, c1, c2, c3;   for( col=0; col<4; col++ )   {      c0 = state[I(0,col)];      c1 = state[I(1,col)];      c2 = state[I(2,col)];      c3 = state[I(3,col)];      // do inverse mixing, and put back into array      state[I(0,col)] = aes_mul(0x0e,c0) ^ aes_mul(0x0b,c1)            ^ aes_mul(0x0d,c2) ^ aes_mul(0x09,c3);      state[I(1,col)] = aes_mul(0x09,c0) ^ aes_mul(0x0e,c1)            ^ aes_mul(0x0b,c2) ^ aes_mul(0x0d,c3);      state[I(2,col)] = aes_mul(0x0d,c0) ^ aes_mul(0x09,c1)            ^ aes_mul(0x0e,c2) ^ aes_mul(0x0b,c3);      state[I(3,col)] = aes_mul(0x0b,c0) ^ aes_mul(0x0d,c1)            ^ aes_mul(0x09,c2) ^ aes_mul(0x0e,c3);   }   return state;}// insert subkey informationfunction AddRoundKey( state, w, base ){   var col;   for( col=0; col<4; col++ )   {      state[I(0,col)] ^= w[base+col*4];      state[I(1,col)] ^= w[base+col*4+1];      state[I(2,col)] ^= w[base+col*4+2];      state[I(3,col)] ^= w[base+col*4+3];   }   return state;}// return a transposed arrayfunction transpose( msg ){   var row, col;   var state = new Array( 16 );   for( row=0; row<4; row++ )      for( col=0; col<4; col++ )         state[I(row,col)] = msg[I(col,row)];   return state;}// final AES statevar AES_output = new Array(16);// format AES output// -- uses the global array DES_outputfunction format_AES_output(){   var i;   var bits;   var str="";   // what type of data do we have to work with?   if ( document.stuff.outtype[0].checked )   {      // convert each set of bits back to ASCII      for( i=0; i<16; i++ )         str += String.fromCharCode( AES_output[i] );   }   else    {      // output hexdecimal data (insert spaces)      str = cvt_hex8( AES_output[0] );      for( i=1; i<16; i++ )      {         str += " " + cvt_hex8( AES_output[i] );      }   }   // copy to textbox   document.stuff.outdata.value = str;}


所有核心代码secret.js【点击下载


Html测试页面:

<BODY>2001年Rijndael算法成为高级加密标准(Advanced Encryption Standard,AES)的获胜者。这个标准用来替代原先的DES,AES的区块长度固定为128比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度均可以是128,192或256比特。<P><form name="stuff"><br>输入一个16个ASCII字符以内的字符串。<p><table><tr>    <td>输入信息:</td>        <td><input type="text" name="indata" size="50" value="abcdefghijklmnop" /></td>        <td><input type="radio" name="intype" checked>ASCII            <input type="radio" name="intype">十六进制        </td></tr><tr>    <td>密钥</td>        <td><select name="key">         <OPTION value="0f1571c947d9e8590cb7add6af7f6798">0f 15 71 c9 47 d9 e8 59 0c b7 ad d6 af 7f 67 98</OPTION>         <OPTION value="f6cc34cdc555c5418254260203ad3ecd">f6 cc 34 cd c5 55 c5 41 82 54 26 02 03 ad 3e cd</OPTION>         <OPTION value="3070971ab7ce45063fd2573f49f5420d">30 70 97 1a b7 ce 45 06 3f d2 57 3f 49 f5 42 0d</OPTION>         <OPTION value="a9aa1f9fd153bcb6c7834212c51f5c41">a9 aa 1f 9f d1 53 bc b6 c7 83 42 12 c5 1f 5c 41</OPTION>         <OPTION value="d2f60c436e7ccebb8eaceaf3f86c8bad">d2 f6 0c 43 6e 7c ce bb 8e ac ea f3 f8 6c 8b ad</OPTION>         <OPTION value="2b7e151628aed2a6abf7158809cf4f3c">2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c</OPTION>       </SELECT></TD>    <TD></TD></TR><TR>    <TD colspan=3 align=center>        <INPUT type="button" value="加密" onClick="aes_encrypt();" />        <INPUT type="button" value="解密" onClick="aes_decrypt();" />        </TD></TR><TR>    <TD>输出信息:</TD>    <TD><INPUT type="text" name="outdata" size="50" /></TD>    <TD><INPUT type="radio" name="outtype" onClick="format_AES_output();">ASCII        <INPUT type="radio" name="outtype" checked onClick="format_AES_output();">十六进制    </TD></TR></TABLE><hr>细节:<BR><TEXTAREA name="details" id="details" rows="25" cols="90"></TEXTAREA></FORM></BODY>


显示页面


Java验证

  private byte[] keys = {            0x0f,0x15,0x71,(byte)0xc9, 0x47,(byte)0xd9,(byte)0xe8,0x59,            0x0c,(byte)0xb7,(byte)0xad,(byte)0xd6,(byte)0xaf,0x7f,0x67,(byte)0x98        };  //KeyGenerator 提供对称密钥生成器的功能,支持各种算法  private KeyGenerator keygen;  //SecretKey 负责保存对称密钥  private SecretKey deskey;  //Cipher负责完成加密或解密工作  private Cipher c;  //该字节数组负责保存加密的结果  private byte[] cipherByte;  public AesDemo() throws NoSuchAlgorithmException, NoSuchPaddingException{    Security.addProvider(new com.sun.crypto.provider.SunJCE());//    //实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)//    keygen = KeyGenerator.getInstance("AES");//    //生成密钥//    deskey = keygen.generateKey();    deskey= new SecretKeySpec(keys, "AES");    System.out.println("密钥:" + UBytes.toHexString(deskey.getEncoded()));    //生成Cipher对象,指定其支持的DES算法    c = Cipher.getInstance("AES/ECB/NOPADDING"); // PKCS5Padding  }  /**   * 对字符串加密   *   * @param str   * @return   * @throws InvalidKeyException   * @throws IllegalBlockSizeException   * @throws BadPaddingException   */  public byte[] Encrytor(String str) throws InvalidKeyException,      IllegalBlockSizeException, BadPaddingException {    // 根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式    c.init(Cipher.ENCRYPT_MODE, deskey);    byte[] src = str.getBytes();    System.out.println("明文:" + UBytes.toHexString(src));    // 加密,结果保存进cipherByte    cipherByte = c.doFinal(src);    System.out.println("密文:" + UBytes.toHexString(cipherByte));    return cipherByte;  }  /**   * 对字符串解密   *   * @param buff   * @return   * @throws InvalidKeyException   * @throws IllegalBlockSizeException   * @throws BadPaddingException   */  public byte[] Decryptor(byte[] buff) throws InvalidKeyException,      IllegalBlockSizeException, BadPaddingException {    // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示加密模式    c.init(Cipher.DECRYPT_MODE, deskey);    cipherByte = c.doFinal(buff);    return cipherByte;  }  /**   * @param args   * @throws NoSuchPaddingException   * @throws NoSuchAlgorithmException   * @throws BadPaddingException   * @throws IllegalBlockSizeException   * @throws InvalidKeyException   */  public static void main(String[] args) throws Exception {    AesDemo de1 = new AesDemo();    String msg ="abcdefghijklmnop";    byte[] encontent = de1.Encrytor(msg);    byte[] decontent = de1.Decryptor(encontent);    System.out.println("解密:" + UBytes.toHexString(decontent));    System.out.println("明文是:" + msg);    System.out.println("加密后:" + new String(encontent));    System.out.println("解密后:" + new String(decontent));  }

结果:

密钥:0F 15 71 C9 47 D9 E8 59 0C B7 AD D6 AF 7F 67 98 明文:61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 密文:11 0A AF F3 F2 D5 6C 9E 69 1A 95 A5 2E 19 28 EB 解密:61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 明文是:abcdefghijklmnop解密后:abcdefghijklmnop


0 0
原创粉丝点击