第8讲-AES候选算法
- 格式:ppt
- 大小:395.50 KB
- 文档页数:25
AES算法加解密原理及安全性分析刘帅卿一、AES算法简介AES算法是高级加密标准算法的简称,其英文名称为Advanced Encryption Standard。
该加密标准的出现是因为随着对称密码的发展,以前使用的DES(Data Encryption Standard数据加密标准)算法由于密钥长度较小(56位),已经不适应当今数据加密安全性的要求,因此后来由Joan Daeman和Vincent Rijmen提交的Rijndael算法被提议为AES的最终算法。
AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥,并且用128位(16字节)分组加密和解密数据。
与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。
通过分组密码返回的加密数据的位数与输入数据相同。
迭代加密使用一个循环结构,在该循环中重复置换(permutations)和替换(substitutions)输入数据。
加之算法本身复杂的加密过程使得该算法成为数据加密领域的主流。
二、AES算法的基本概念1、有限域(GF)由于AES算法中的所有运算都是在有限域当中进行的,所以在理解和实现该算法之前先得打好有限域这一基石才行。
通常的数学运算都是在实数域中进行,而AES算法则是在有限域中进行,我们可以将有限域看成是有确定边界范围的正整数集合,在该集合当中,任意两个元素之间的运算结果都仍然落在该集合当中,也即满足运算封闭性。
那么如何才能保证这样的“有限性”(也即封闭性)呢?GF(2w)被称之为伽罗华域,是有限域的典型代表。
随着w(=4,8,16,…)的取值不同所形成的有限域范围也不同。
AES算法中引入了GF域当中对数学运算的基本定义:将两数的加减法定义为两者的异或运算;将两数的乘法定义为多项式间的相乘并求余运算,其中被用于求余运算的除数被称为不可约多项式(或者称为求余多项式),它是固定的一个多项式:m(x) =8431x x x x ++++(数值为十六进制的11B ,这里是假定w=8时的情形)。
fleshwound2005-12-03 21:46// $Id: $//// $Log: $// Revision 1.0.1 1998/04/13 raif// + slightly improved performance.//// Revision 1.0 1998/04/07 raif// + original version.//// $Endlog$/** Copyright (c) 1997, 1998 Systemics Ltd on behalf of* the Cryptix Development Team. All rights reserved.*/package DEAL;import java.io.PrintWriter;import java.security.InvalidKeyException;//.........................................................................../*** DEAL is a 128-bit, variable key-size (128-, 192- and 256-bit) symmetric* cipher.<p>** DEAL was designed by <a href="mailto:lars.knudsen@ii.uib.no">Lars Ramkilde* Knudsen</a> and is described by the designer in: DEAL -- A 128-bit Block * Cipher, February 21, 1998 (postscript file).<p>** <b>Copyright</b> © 1997, 1998* <a href="/">Systemics Ltd</a> on behalf of the * <a href="/docs/cryptix/">Cryptix Development Team</a>.* <br>All rights reserved.<p>** <b>$Revision: $</b>* @author Raif S. Naffah*/public final class DEAL_Algorithm // implicit no-argument constructor{// Debugging methods and variables//...........................................................................static final String NAME = "DEAL_Algorithm";static final boolean IN = true, OUT = false;static final boolean DEBUG = DEAL_Properties.GLOBAL_DEBUG;static final int debuglevel = DEBUG ? DEAL_Properties.getLevel(NAME) : 0; static final PrintWriter err = DEBUG ? DEAL_Properties.getOutput() : null;static final boolean TRACE = DEAL_Properties.isTraceable(NAME);static void debug (String s) { err.println(">>> "+NAME+": "+s); }static void trace (boolean in, String s) {if (TRACE) err.println((in?"==> ":"<== ")+NAME+"."+s);}static void trace (String s) { if (TRACE) err.println("<=> "+NAME+"."+s); }// Constants and variables//...........................................................................static final int BLOCK_SIZE = 16; // block size in bytesprivate static final char[] HEX_DIGITS = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};// Basic API methods//.........................................................................../*** Expand a user-supplied key material into a session key.** @param key The 128/192/256-bit user-key to use.* @exception InvalidKeyException If the key is invalid.*/public static synchronized Object makeKey (byte[] k)throws InvalidKeyException {if (DEBUG) trace(IN, "makeKey("+k+")");if (k == null)throw new InvalidKeyException("Empty key");int s = k.length / 8;if (!(s == 2 || s == 3 || s == 4))throw new InvalidKeyException("Incorrect key length");if (DEBUG && debuglevel > 7) {System.out.println("Intermediate Session Key Values");System.out.println();System.out.println("Raw="+toString(k));}//// format user key material into K[] DES key material objects// each being 64-bit wide; ie. an array of 8 bytes//byte[][] K = new byte[s][8];int i, j, offset = 0;for (i = 0; i < s; i++)for (j = 0; j < 8; j++)K[i][j] = k[offset++];//// out of these s DES keys make r new DES keys RK[]; r being// the appropriate number of rounds for the given user key// material supplied//// NOTE: --RSN 1998/04/15// Although the next 2 lines are correct, the code generation// (tested with jdk-115 on win95B) may yield incorrect results// depending on wether the -O switch is set or not when compiling // with javac. Not using the -O switch always result in correct// values.//// The current code seems to work correctly with and without the // -O switch of javac.//// int r = getRounds(k.length);// byte[][] RK = new byte[r][8];byte[][] RK = null;// the formulae for computing RK[] use a fixed DES key, we'll// note it as Kfbyte[] Kf = new byte[] {0x01, 0x23, 0x45, 0x67,(byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF };Object Ek = DES_Algorithm.makeKey(Kf);// three cases are possible depending on the value of sswitch (s) {case 2:RK = new byte[6][8];RK[0] = DES_Algorithm.blockEncrypt( K[0], 0, Ek);RK[1] = DES_Algorithm.blockEncrypt(xor( K[1], RK[0]), 0, Ek);RK[2] = DES_Algorithm.blockEncrypt(xor(xor(K[0], 1), RK[1]), 0, Ek);RK[3] = DES_Algorithm.blockEncrypt(xor(xor(K[1], 2), RK[2]), 0, Ek);RK[4] = DES_Algorithm.blockEncrypt(xor(xor(K[0], 3), RK[3]), 0, Ek);RK[5] = DES_Algorithm.blockEncrypt(xor(xor(K[1], 4), RK[4]), 0, Ek);break;case 3:RK = new byte[6][8];RK[0] = DES_Algorithm.blockEncrypt( K[0], 0, Ek);RK[1] = DES_Algorithm.blockEncrypt(xor( K[1], RK[0]), 0, Ek);RK[2] = DES_Algorithm.blockEncrypt(xor( K[2], RK[1]), 0, Ek);RK[3] = DES_Algorithm.blockEncrypt(xor(xor(K[0], 1), RK[2]), 0, Ek);RK[4] = DES_Algorithm.blockEncrypt(xor(xor(K[1], 2), RK[3]), 0, Ek);RK[5] = DES_Algorithm.blockEncrypt(xor(xor(K[2], 3), RK[4]), 0, Ek);break;case 4:RK = new byte[8][8];RK[0] = DES_Algorithm.blockEncrypt( K[0], 0, Ek);RK[1] = DES_Algorithm.blockEncrypt(xor( K[1], RK[0]), 0, Ek);RK[2] = DES_Algorithm.blockEncrypt(xor( K[2], RK[1]), 0, Ek);RK[3] = DES_Algorithm.blockEncrypt(xor( K[3], RK[2]), 0, Ek);RK[4] = DES_Algorithm.blockEncrypt(xor(xor(K[0], 1), RK[3]), 0, Ek);RK[5] = DES_Algorithm.blockEncrypt(xor(xor(K[1], 2), RK[4]), 0, Ek);RK[6] = DES_Algorithm.blockEncrypt(xor(xor(K[2], 3), RK[5]), 0, Ek);RK[7] = DES_Algorithm.blockEncrypt(xor(xor(K[3], 4), RK[6]), 0, Ek);break;}if (DEBUG && debuglevel > 7) {//for (i=0;i<r;i++) System.out.println("RK"+i+"="+toString(RK[i]));for (i=0;i<RK.length;i++) System.out.println("RK"+i+"="+toString(RK[i])); System.out.println();}// DEAL session keys become then the set of the r session keys built// using the RK[]// Object[] sessionKey = new Object[r];Object[] sessionKey = new Object[RK.length];// for (i = 0; i < r; i++)for (i = 0; i < RK.length; i++)sessionKey[i] = DES_Algorithm.makeKey(RK[i]);if (DEBUG) trace(OUT, "makeKey()");return sessionKey;}/*** Encrypt exactly one block of plaintext.** @param in The plaintext.* @param inOffset Index of in from which to start considering data.* @param sessionKey The session key to use for encryption.* @return The ciphertext generated from a plaintext using the session key. */public static byte[]blockEncrypt (byte[] in, int inOffset, Object sessionKey) {if (DEBUG) trace(IN, "blockEncrypt("+in+", "+inOffset+", "+sessionKey+")");Object[] rKey = (Object[]) sessionKey; // re-cast sessionKey to round keys int rounds = rKey.length;byte[] L0 = new byte[8]; // divide input into 2 64-bit entitiesbyte[] R0 = new byte[8];byte[] L1, R1; // temp arraysSystem.arraycopy(in, inOffset, L0, 0, 8);System.arraycopy(in, inOffset + 8, R0, 0, 8);if (DEBUG && debuglevel > 6) System.out.println("PT="+toString(L0)+""+toString(R0));DES_Algorithm.IP(L0); // apply DES IP to both sidesDES_Algorithm.IP(R0);if (DEBUG && debuglevel > 6) System.out.println("IP(PT)="+toString(L0)+" "+toString(R0));R1 = (byte[]) L0.clone(); // j = 1DES_Algorithm.encrypt(L0, rKey[0]);L1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("CT1="+toString(L1)+""+toString(R1));R0 = (byte[]) L1.clone(); // j = 2DES_Algorithm.encrypt(L1, rKey[1]);L0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("CT2="+toString(L0)+""+toString(R0));R1 = (byte[]) L0.clone(); // j = 3DES_Algorithm.encrypt(L0, rKey[2]);L1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("CT3="+toString(L1)+""+toString(R1));R0 = (byte[]) L1.clone(); // j = 4DES_Algorithm.encrypt(L1, rKey[3]);L0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("CT4="+toString(L0)+" "+toString(R0));R1 = (byte[]) L0.clone(); // j = 5DES_Algorithm.encrypt(L0, rKey[4]);L1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("CT5="+toString(L1)+" "+toString(R1));R0 = (byte[]) L1.clone(); // j = 6DES_Algorithm.encrypt(L1, rKey[5]);L0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("CT6="+toString(L0)+" "+toString(R0));if (rounds == 8) {R1 = (byte[]) L0.clone(); // j = 7DES_Algorithm.encrypt(L0, rKey[6]);L1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("CT7="+toString(L1)+" "+toString(R1));R0 = (byte[]) L1.clone(); // j = 8DES_Algorithm.encrypt(L1, rKey[7]);L0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("CT8="+toString(L0)+" "+toString(R0));}DES_Algorithm.FP(L0); // apply DES FP to both sidesDES_Algorithm.FP(R0);if (DEBUG && debuglevel > 6) {System.out.println("CT="+toString(L0)+" "+toString(R0));System.out.println();}byte[] result = new byte[16];System.arraycopy(L0, 0, result, 0, 8);System.arraycopy(R0, 0, result, 8, 8);if (DEBUG) trace(OUT, "blockEncrypt()");return result;}/*** Decrypt exactly one block of ciphertext.** @param in The ciphertext.* @param inOffset Index of in from which to start considering data.* @param sessionKey The session key to use for decryption.* @return The plaintext generated from a ciphertext using the session key. */public static byte[]blockDecrypt (byte[] in, int inOffset, Object sessionKey) {if (DEBUG) trace(IN, "blockDecrypt("+in+", "+inOffset+", "+sessionKey+")");Object[] rKey = (Object[]) sessionKey; // re-cast sessionKey to round keys int rounds = rKey.length;byte[] L1 = new byte[8]; // divide input into 2 64-bit entitiesbyte[] R1 = new byte[8];byte[] L0, R0; // temp arraysSystem.arraycopy(in, inOffset, L1, 0, 8);System.arraycopy(in, inOffset + 8, R1, 0, 8);if (DEBUG && debuglevel > 6) System.out.println("CT="+toString(L1)+""+toString(R1));DES_Algorithm.IP(L1); // apply DES IP to both sidesDES_Algorithm.IP(R1);if (DEBUG && debuglevel > 6) System.out.println("IP(CT)="+toString(L1)+" "+toString(R1));if (rounds == 8) {L0 = (byte[]) R1.clone(); // j = 8DES_Algorithm.encrypt(R1, rKey[7]);R0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("PT8="+toString(L0)+""+toString(R0));L1 = (byte[]) R0.clone(); // j = 7DES_Algorithm.encrypt(R0, rKey[6]);R1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("PT7="+toString(L1)+""+toString(R1));}L0 = (byte[]) R1.clone(); // j = 6DES_Algorithm.encrypt(R1, rKey[5]);R0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("PT6="+toString(L0)+""+toString(R0));L1 = (byte[]) R0.clone(); // j = 5DES_Algorithm.encrypt(R0, rKey[4]);R1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("PT5="+toString(L1)+" "+toString(R1));L0 = (byte[]) R1.clone(); // j = 4DES_Algorithm.encrypt(R1, rKey[3]);R0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("PT4="+toString(L0)+" "+toString(R0));L1 = (byte[]) R0.clone(); // j = 3DES_Algorithm.encrypt(R0, rKey[2]);R1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("PT3="+toString(L1)+" "+toString(R1));L0 = (byte[]) R1.clone(); // j = 2DES_Algorithm.encrypt(R1, rKey[1]);R0 = xor(L1, R1);if (DEBUG && debuglevel > 6) System.out.println("PT2="+toString(L0)+" "+toString(R0));L1 = (byte[]) R0.clone(); // j = 1DES_Algorithm.encrypt(R0, rKey[0]);R1 = xor(L0, R0);if (DEBUG && debuglevel > 6) System.out.println("PT1="+toString(L1)+" "+toString(R1));DES_Algorithm.FP(L1); // apply DES FP to both sidesDES_Algorithm.FP(R1);if (DEBUG && debuglevel > 6) {System.out.println("PT="+toString(L1)+" "+toString(R1));System.out.println();}byte[] result = new byte[16];System.arraycopy(L1, 0, result, 0, 8);System.arraycopy(R1, 0, result, 8, 8);if (DEBUG) trace(OUT, "blockDecrypt()");return result;}/** A basic symmetric encryption/decryption test. */public static boolean self_test() {boolean ok = DES_Algorithm.self_test();try {if (!ok)throw new RuntimeException("DES self-test failed");byte[] kb = new byte[] {(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67,(byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF,(byte) 0x10, (byte) 0x32, (byte) 0x54, (byte) 0x76,(byte) 0x98, (byte) 0xBA, (byte) 0xDC, (byte) 0xFE };byte[] pt = fromString("0123456789ABCDEF1032547698BADCFE");byte[] ct = fromString("419C64EC7C579C4CAC81A4ED78D9374B");int i;Object key = makeKey(kb);byte[] tmp = blockEncrypt(pt, 0, key);ok = areEqual(ct, tmp);if (!ok) {if (DEBUG && debuglevel > 0) {debug("KAT single triple");debug(" key: " + toString(kb));debug(" plaintext: " + toString(pt));debug("ciphertext: " + toString(ct));debug(" computed: " + toString(tmp));}throw new RuntimeException("Encryption failed");}tmp = blockDecrypt(ct, 0, key);ok = areEqual(pt, tmp);if (!ok) {if (DEBUG && debuglevel > 0) {debug("KAT single triple");debug(" key: " + toString(kb));debug("ciphertext: " + toString(ct));debug(" plaintext: " + toString(pt));debug(" computed: " + toString(tmp));}throw new RuntimeException("Decryption failed");}if (DEBUG && debuglevel > 0) debug("KAT (single triple) OK? " + ok);ok = self_test(BLOCK_SIZE);} catch (Exception x) {if (DEBUG && debuglevel > 0) {debug("Exception encountered during self-test: " + x.getMessage());x.printStackTrace();}}if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok);if (DEBUG) trace(OUT, "self_test()");return ok;}// own methods//.........................................................................../** @return The length in bytes of DEAL's input block. */public static int blockSize() { return BLOCK_SIZE; }/*** Return The number of rounds for a given DEAL's user key size.** @param keySize The size of the user key material in bytes.* @return The number of rounds for this DEAL.*/public static final int getRounds (int keySize) {if (DEBUG) trace(IN, "getRounds("+keySize+")");switch (keySize) {case 16:case 24:if (DEBUG) trace(OUT, "getRounds() --> 6");return 6;case 32:default:if (DEBUG) trace(OUT, "getRounds() --> 8");return 8;}}/** @return A 64-bit entity = x ^ y. */private static final byte[] xor (byte[] x, byte[] y) {byte[] result = (byte[]) x.clone();for (int i = 0; i < 8; i++)result[i] ^= y[i];return result;}/*** @param x A DES key as a byte[].* @param y A bit number/position in a 64-bit ordinal string where the* <i>y</i><sup>th</sup> bit (and no other) is set. Allowed values * for <i>y</i> are 1, 2, 3 and 4. The bits are numbered, as described * in FIPS 46-2 (Data Encryption Standard --DES), from left to right, * ie. the left most bit of the block is bit zero.* @return A 64-bit entity result of xoring both input values together.*/private static final byte[] xor (byte[] x, int y) {byte[] result = (byte[]) x.clone();result[0] ^= (0x80 >>> (y-1)) & 0xFF;return result;}/** A basic symmetric encryption/decryption test for a given key size. */ private static boolean self_test (int keysize) {if (DEBUG) trace(IN, "self_test("+keysize+")");boolean ok = false;try {byte[] kb = new byte[keysize];byte[] pt = new byte[BLOCK_SIZE];int i;// kb[0] = (byte) 0x80;for (i = 0; i < keysize; i++)kb[i] = (byte) i;for (i = 0; i < BLOCK_SIZE; i++)pt[i] = (byte) i;if (DEBUG && debuglevel > 6) {System.out.println("==========");System.out.println();System.out.println("KEYSIZE="+(8*keysize));System.out.println("KEY="+toString(kb));System.out.println();}Object key = makeKey(kb);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Ciphertext Values (Encryption)"); System.out.println();}byte[] ct = blockEncrypt(pt, 0, key);if (DEBUG && debuglevel > 6) {System.out.println("Intermediate Plaintext Values (Decryption)"); System.out.println();}byte[] cpt = blockDecrypt(ct, 0, key);ok = areEqual(pt, cpt);if (!ok) {if (DEBUG && debuglevel > 0) {debug(" key: " + toString(kb));debug(" plaintext: " + toString(pt));debug("ciphertext: " + toString(ct));debug(" computed: " + toString(cpt));}throw new RuntimeException("Symmetric operation failed");}} catch (Exception x) {if (DEBUG && debuglevel > 0) {debug("Exception encountered during self-test: " + x.getMessage()); x.printStackTrace();}}if (DEBUG && debuglevel > 0) debug("Self-test OK? " + ok);if (DEBUG) trace(OUT, "self_test()");return ok;}// utility static methods (from cryptix.util.core ArrayUtil and Hex classes) //.........................................................................../*** Compares two byte arrays for equality.** @return true if the arrays have identical contents*/private static final boolean areEqual (byte[] a, byte[] b) {int aLength = a.length;if (aLength != b.length)return false;for (int i = 0; i < aLength; i++)if (a[i] != b[i])return false;return true;}/** Returns a byte array from a string of hexadecimal digits. */ private static byte[] fromString (String hex) {int len = hex.length();byte[] buf = new byte[((len + 1) / 2)];int i = 0, j = 0;if ((len % 2) == 1)buf[j++] = (byte) fromDigit(hex.charAt(i++));while (i < len) {buf[j++] = (byte)((fromDigit(hex.charAt(i++)) << 4) |fromDigit(hex.charAt(i++)));}return buf;}/*** Returns a number from 0 to 15 corresponding to the hex* digit <i>ch</i>.*/public static int fromDigit (char ch) {if (ch >= '0' && ch <= '9')return ch - '0';if (ch >= 'A' && ch <= 'F')return ch - 'A' + 10;if (ch >= 'a' && ch <= 'f')return ch - 'a' + 10;throw new IllegalArgumentException("Invalid hex digit '"+ch+"'"); }/*** Returns a string of hexadecimal digits from a byte array. Each* byte is converted to 2 hex symbols.*/private static final String toString (byte[] ba) {int length = ba.length;char[] buf = new char[length * 2];for (int i = 0, j = 0, k; i < length; ) {k = ba[i++];buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F];buf[j++] = HEX_DIGITS[ k & 0x0F];}return new String(buf);}// main(): use to generate the Intermediate Values KAT//...........................................................................fleshwound2005-12-03 21:46// $Id: $//// $Log: $// Revision 1.0 1998/04/07 raif// + start of history.//// $Endlog$/** Copyright (c) 1997, 1998 Systemics Ltd on behalf of* the Cryptix Development Team. All rights reserved.*/package DEAL;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.InputStream;import java.io.IOException;import java.io.PrintWriter;import java.io.PrintStream;import java.util.Enumeration;import java.util.Properties;/*** This class acts as a central repository for an algorithm specific* properties. It reads an (algorithm).properties file containing algorithm-* specific properties. When using the AES-Kit, this (algorithm).properties* file is located in the (algorithm).jar file produced by the "jarit" batch/* script command.<p>** <b>Copyright</b> © 1997, 1998* <a href="/">Systemics Ltd</a> on behalf of the * <a href="/docs/cryptix/">Cryptix Development Team</a>.* <br>All rights reserved.<p>** <b>$Revision: $</b>* @author David Hopwood* @author Jill Baker* @author Raif S. Naffah*/public class DEAL_Properties // implicit no-argument constructor{// Constants and variables with relevant static code//...........................................................................static final boolean GLOBAL_DEBUG = false;static final String ALGORITHM = "DEAL";static final double VERSION = 0.1;static final String FULL_NAME = ALGORITHM + " ver. " + VERSION;static final String NAME = "DEAL_Properties";static final Properties properties = new Properties();/** Default properties in case .properties file was not found. */private static final String[][] DEFAULT_PROPERTIES = {{"Trace.DEAL_Algorithm", "true"},{"Trace.DES_Algorithm", "true"},{"Debug.Level.*", "1"},{"Debug.Level.DEAL_Algorithm", "9"},{"Debug.Level.DES_Algorithm", "9"}};static {if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Looking for " + ALGORITHM + " properties");String it = ALGORITHM + ".properties";InputStream is = DEAL_Properties.class.getResourceAsStream(it);boolean ok = is != null;if (ok)try {properties.load(is);is.close();if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Properties file loaded OK...");} catch (Exception x) {ok = false;}if (!ok) {if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": WARNING: Unable to load \"" + it + "\" from CLASSPATH.");if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Will use default values instead...");int n = DEFAULT_PROPERTIES.length;for (int i = 0; i < n; i++)properties.put(DEFAULT_PROPERTIES[i][0], DEFAULT_PROPERTIES[i][1]);if (GLOBAL_DEBUG) System.err.println(">>> " + NAME + ": Default properties now set...");}}// Properties methods (excluding load and save, which are deliberately not// supported).//.........................................................................../** Get the value of a property for this algorithm. */public static String getProperty (String key) {return properties.getProperty(key);}/*** Get the value of a property for this algorithm, or return* <i>value</i> if the property was not set.*/public static String getProperty (String key, String value) {return properties.getProperty(key, value);}/** List algorithm properties to the PrintStream <i>out</i>. */public static void list (PrintStream out) {list(new PrintWriter(out, true));}/** List algorithm properties to the PrintWriter <i>out</i>. */public static void list (PrintWriter out) {out.println("#");out.println("# ----- Begin "+ALGORITHM+" properties -----");out.println("#");String key, value;Enumeration enum = properties.propertyNames();while (enum.hasMoreElements()) {key = (String) enum.nextElement();value = getProperty(key);out.println(key + " = " + value);}out.println("#");out.println("# ----- End "+ALGORITHM+" properties -----");}// public synchronized void load(InputStream in) throws IOException {}public static Enumeration propertyNames() {return properties.propertyNames();}// public void save (OutputStream os, String comment) {}// Developer support: Tracing and debugging enquiry methods(package-private)//.........................................................................../*** Return true if tracing is requested for a given class.<p>** User indicates this by setting the tracing <code>boolean</code>* property for <i>label</i> in the <code>(algorithm).properties</code> * file. The property's key is "<code>Trace.<i>label</i></code>".<p> ** @param label The name of a class.* @return True iff a boolean true value is set for a property with* the key <code>Trace.<i>label</i></code>.*/static boolean isTraceable (String label) {String s = getProperty("Trace." + label);if (s == null)return false;return new Boolean(s).booleanValue();}/*** Return the debug level for a given class.<p>** User indicates this by setting the numeric property with key* "<code>Debug.Level.<i>label</i></code>".<p>** If this property is not set, "<code>Debug.Level.*</code>" is looked up* next. If neither property is set, or if the first property found is* not a valid decimal integer, then this method returns 0.** @param label The name of a class.* @return The required debugging level for the designated class.*/static int getLevel(String label) {String s = getProperty("Debug.Level." + label);if (s == null) {s = getProperty("Debug.Level.*");if (s == null)return 0;}try {return Integer.parseInt(s);} catch (NumberFormatException e) {return 0;}}/*** Return the PrintWriter to which tracing and debugging output is to* be sent.<p>** User indicates this by setting the property with key <code>Output</code> * to the literal <code>out</code> or <code>err</code>.<p>** By default or if the set value is not allowed, <code>System.err</code>* will be used.*/static PrintWriter getOutput() {PrintWriter pw;String name = getProperty("Output");if (name != null && name.equals("out"))pw = new PrintWriter(System.out, true);else。
AES算法介绍1. AES算法简介AES算法是高级加密标准算法的简称,其英文名称为Advanced Encryption Standard。
该加密标准的出现是因为随着对称密码的发展,以前使用的DES(Data Encryption Standard数据加密标准)算法由于密钥长度较小(56位),已经不适应当今数据加密安全性的要求,因此后来由Joan Daeman和Vincent Rijmen提交的Rijndael算法被提议为AES的最终算法。
AES算法所能支持的密钥长度可以为128,192,256位(也即16,24,32个字节)。
加之算法本身复杂的加密过程使得该算法成为数据加密领域的主流。
2. AES算法的基本概念(1)有限域(GF)由于AES算法中的所有运算都是在有限域当中进行的,所以在理解和实现该算法之前先得打好有限域这一基石才行。
通常的数学运算都是在实数域中进行,而AES算法则是在有限域中进行,我们可以将有限域看成是有确定边界范围的正整数集合,在该集合当中,任意两个元素之间的运算结果都仍然落在该集合当中,也即满足运算封闭性。
那么如何才能保证这样的“有限性”(也即封闭性)呢?GF(2w)被称之为伽罗华域,是有限域的典型代表。
随着w(=4,8,16,?)的取值不同所形成的有限域范围也不同。
AES算法中引入了GF域当中对数学运算的基本定义:将两数的加减法定义为两者的异或运算;将两数的乘法定义为多项式间的相乘并求余运算,其中被用于求余运算的除数被称为不可约多项式(或者称为求余多项式),它是固定的一个多项式:m(x) =x?x?x?x?1(数值为十六进制的11B,这里是假定w=8时的情形)。
对于某个有限域而言,可能存在不唯一的不可约多项式,选择合适的多项式是某种算法考虑的主要因素之一。
有了上述对数学运算的基本定义,就可以实现运算的有限性了。
对于有限域具体的运算过程和实例演示可参照有关资料。
这里不再赘述。
AES算法详解AES算法简介 AES的全称是Advanced Encryption Standard,意思是⾼级加密标准。
AES密码分组⼤⼩和密钥⼤⼩可以为128位、192位和256位。
然⽽AES只要求分组⼤⼩为128位。
本⽂只对分组⼤⼩128位,密钥长度也为128位的Rijndael算法进⾏分析。
密钥长度为192位和256位的处理⽅式和128位的处理⽅式类似,只不过密钥长度每增加64位,算法的循环次数就增加2轮,128位循环10轮、192位循环12轮、256位循环14轮。
AES算法使⽤逻辑就是:发送⽅将要发送的明⽂数据X使⽤秘钥K进⾏AES加密后会得到密⽂Y,将密⽂进⾏⽹络传输,接受⽅在收到密⽂Y后使⽤秘钥K进⾏AES解密后技能得到明⽂X,这样即使密⽂Y在⽹络上传输时被截获了,没有秘钥也难以破解其真实意思。
AES算法相关数学知识 在AES算法中的MixColumn层中会⽤到伽罗⽡域中的乘法运算,⽽伽罗⽡域的运算涉及⼀些数学知识如下:素域: 有限域有时也称伽罗⽡域,它指的是由有限个元素组成的集合,在这个集合内可以执⾏加、减、乘和逆运算。
⽽在密码编码学中,我们只研究拥有有限个元素的域,也就是有限域。
域中包含元素的个数称为域的阶。
只有当m是⼀个素数幂时,即m=p n(其中n为正整数是p的次数,p为素数),阶为m的域才存在。
p称为这个有限域的特征。
也就是说,有限域中元素的个数可以是11(p=11是⼀个素数,n=1)、可以是81(p=3是⼀个素数,n=4)、也可以是256(p=2是⼀个素数,n=8).....但有限域的中不可能拥有12个元素,因为12=2·2·3,因此12也不是⼀个素数幂。
有限域中最直观的例⼦就是阶为素数的域,即n=1的域。
的元素可以⽤整数0、1、...、p-1l来表⽰。
域的两种操作就是模整数加法和整数乘法模p。
加上p是⼀个素数,整数环Z表⽰为GF(p),也成为拥有素数个元素的素数域或者伽罗⽡域。
解释aes算法
AES算法是一种对称加密算法,全称为高级加密标准算法(Advanced Encryption Standard),它是一种广泛使用的加密算法,用于保护数据的机密性。
AES算法采用分组密码技术,将明文分成固定长度的块,然后分别对每个块进行加密。
加密的过程中,AES算法使用了多轮迭代加密算法,每轮迭代包括四个步骤:字节代替、行移位、列混淆和轮密钥加。
这些步骤一起构成了AES算法的核心。
AES算法使用的密钥长度可以是128位、192位或256位,密钥长度越长,破解的难度就越大。
AES算法的强大安全性和高效性,使其成为许多应用程序中首选的加密算法。
然而,AES算法并不是绝对安全的,只要攻击者有足够的计算能力和时间,就可以破解AES加密。
总之,AES算法是一种可靠的加密算法,它可以保护敏感数据的安全性,但同时也需要注意其安全性的弱点,以保证数据的机密性。
- 1 -。
AES算法⾼级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信⼩程序加密传输就是⽤这个加密算法的)。
对称加密算法也就是加密和解密⽤相同的密钥,具体的加密流程如下图:明⽂P密钥KAES加密函数设AES加密函数为E,则 C = E(K, P),其中P为明⽂,K为密钥,C为密⽂。
也就是说,把明⽂P和密钥K作为加密函数的参数输⼊,则加密函数E会输出密⽂C。
密⽂CAES的基本结构AES为分组密码,分组密码也就是把明⽂分成⼀组⼀组的,每组长度相等,每次加密⼀组数据,直到加密完整个明⽂。
在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。
密钥的长度可以使⽤128位、192位或256位。
密钥的长度不同,推荐加密轮数也不同,如下表所⽰:轮数在下⾯介绍,这⾥实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。
上⾯说到,AES的加密公式为C = E(K,P),在加密函数E中,会执⾏⼀个轮函数,并且执⾏10次这个轮函数,这个轮函数的前9次执⾏的操作是⼀样的,只有第10次有所不同。
也就是说,⼀个明⽂分组会被加密10轮。
AES的核⼼就是实现⼀轮中的所有操作。
AES的处理单位是字节,128位的输⼊明⽂分组P和输⼊密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。
如,明⽂分组为P = abcdefghijklmnop,其中的字符a对应P0,p对应P15。
⼀般地,明⽂分组⽤字节为单位的正⽅形矩阵描述,称为状态矩阵。
在算法的每⼀轮中,状态矩阵的内容不断发⽣变化,最后的结果作为密⽂输出。
该矩阵中字节的排列顺序为从上到下、从左⾄右依次排列,如下图所⽰:现在假设明⽂分组P为"abcdefghijklmnop",则对应上⾯⽣成的状态矩阵图如下:类似地,128位密钥也是⽤字节为单位的矩阵表⽰,矩阵的每⼀列被称为1个32位⽐特字。