35 */
36
37 package com.sun.crypto.provider;
38
39 import java.security.InvalidKeyException;
40 import java.security.MessageDigest;
41
42 /**
43 * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
44 * block size and variable key-size (128-, 192- and 256-bit).
45 * <p>
46 * Rijndael was designed by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
47 * Rijmen</a> and <a href="mailto:Joan.Daemen@village.uunet.be">Joan Daemen</a>.
48 */
49 final class AESCrypt extends SymmetricCipher implements AESConstants
50 {
51 private boolean ROUNDS_12 = false;
52 private boolean ROUNDS_14 = false;
53
54 /** Session and Sub keys */
55 private Object[] sessionK = null;
56 private int[] K = null;
57
58 /** Cipher encryption/decryption key */
59 // skip re-generating Session and Sub keys if the cipher key is
60 // the same
61 private byte[] lastKey = null;
62
63 /** ROUNDS * 4 */
64 private int limit = 0;
65
66 AESCrypt() {
67 // empty
68 }
69
70 /**
71 * Returns this cipher's block size.
72 *
73 * @return this cipher's block size
74 */
75 int getBlockSize() {
78
79 void init(boolean decrypting, String algorithm, byte[] key)
80 throws InvalidKeyException {
81 if (!algorithm.equalsIgnoreCase("AES")
82 && !algorithm.equalsIgnoreCase("Rijndael")) {
83 throw new InvalidKeyException
84 ("Wrong algorithm: AES or Rijndael required");
85 }
86 if (!isKeySizeValid(key.length)) {
87 throw new InvalidKeyException("Invalid AES key length: " +
88 key.length + " bytes");
89 }
90
91 if (!MessageDigest.isEqual(key, lastKey)) {
92 // re-generate session key 'sessionK' when cipher key changes
93 makeSessionKey(key);
94 lastKey = key.clone(); // save cipher key
95 }
96
97 // set sub key to the corresponding session Key
98 this.K = (int[]) sessionK[(decrypting? 1:0)];
99 }
100
101 /**
102 * Expand an int[(ROUNDS+1)][4] into int[(ROUNDS+1)*4].
103 * For decryption round keys, need to rotate right by 4 ints.
104 * @param kr The round keys for encryption or decryption.
105 * @param decrypting True if 'kr' is for decryption and false otherwise.
106 */
107 private static final int[] expandToSubKey(int[][] kr, boolean decrypting) {
108 int total = kr.length;
109 int[] expK = new int[total*4];
110 if (decrypting) {
111 // decrypting, rotate right by 4 ints
112 // i.e. i==0
113 for(int j=0; j<4; j++) {
114 expK[j] = kr[total-1][j];
115 }
116 for(int i=1; i<total; i++) {
117 for(int j=0; j<4; j++) {
118 expK[i*4 + j] = kr[i-1][j];
643 // inverse MixColumn where needed
644 for (j = 0; j < BC; j++) {
645 tt = Kd[r][j];
646 Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^
647 U2[(tt >>> 16) & 0xFF] ^
648 U3[(tt >>> 8) & 0xFF] ^
649 U4[ tt & 0xFF];
650 }
651 }
652
653 // assemble the encryption (Ke) and decryption (Kd) round keys
654 // and expand them into arrays of ints.
655 int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
656 int[] expandedKd = expandToSubKey(Kd, true); // decrypting==true
657
658 ROUNDS_12 = (ROUNDS>=12);
659 ROUNDS_14 = (ROUNDS==14);
660 limit = ROUNDS*4;
661
662 // store the expanded sub keys into 'sessionK'
663 sessionK = new Object[] { expandedKe, expandedKd };
664 }
665
666
667 /**
668 * Return The number of rounds for a given Rijndael keysize.
669 *
670 * @param keySize The size of the user key material in bytes.
671 * MUST be one of (16, 24, 32).
672 * @return The number of rounds.
673 */
674 private static int getRounds(int keySize) {
675 return (keySize >> 2) + 6;
676 }
677 }
|
35 */
36
37 package com.sun.crypto.provider;
38
39 import java.security.InvalidKeyException;
40 import java.security.MessageDigest;
41
42 /**
43 * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
44 * block size and variable key-size (128-, 192- and 256-bit).
45 * <p>
46 * Rijndael was designed by <a href="mailto:rijmen@esat.kuleuven.ac.be">Vincent
47 * Rijmen</a> and <a href="mailto:Joan.Daemen@village.uunet.be">Joan Daemen</a>.
48 */
49 final class AESCrypt extends SymmetricCipher implements AESConstants
50 {
51 private boolean ROUNDS_12 = false;
52 private boolean ROUNDS_14 = false;
53
54 /** Session and Sub keys */
55 private int[][] sessionK = null;
56 private int[] K = null;
57
58 /** Cipher encryption/decryption key */
59 // skip re-generating Session and Sub keys if the cipher key is
60 // the same
61 private byte[] lastKey = null;
62
63 /** ROUNDS * 4 */
64 private int limit = 0;
65
66 AESCrypt() {
67 // empty
68 }
69
70 /**
71 * Returns this cipher's block size.
72 *
73 * @return this cipher's block size
74 */
75 int getBlockSize() {
78
79 void init(boolean decrypting, String algorithm, byte[] key)
80 throws InvalidKeyException {
81 if (!algorithm.equalsIgnoreCase("AES")
82 && !algorithm.equalsIgnoreCase("Rijndael")) {
83 throw new InvalidKeyException
84 ("Wrong algorithm: AES or Rijndael required");
85 }
86 if (!isKeySizeValid(key.length)) {
87 throw new InvalidKeyException("Invalid AES key length: " +
88 key.length + " bytes");
89 }
90
91 if (!MessageDigest.isEqual(key, lastKey)) {
92 // re-generate session key 'sessionK' when cipher key changes
93 makeSessionKey(key);
94 lastKey = key.clone(); // save cipher key
95 }
96
97 // set sub key to the corresponding session Key
98 this.K = sessionK[(decrypting? 1:0)];
99 }
100
101 /**
102 * Expand an int[(ROUNDS+1)][4] into int[(ROUNDS+1)*4].
103 * For decryption round keys, need to rotate right by 4 ints.
104 * @param kr The round keys for encryption or decryption.
105 * @param decrypting True if 'kr' is for decryption and false otherwise.
106 */
107 private static final int[] expandToSubKey(int[][] kr, boolean decrypting) {
108 int total = kr.length;
109 int[] expK = new int[total*4];
110 if (decrypting) {
111 // decrypting, rotate right by 4 ints
112 // i.e. i==0
113 for(int j=0; j<4; j++) {
114 expK[j] = kr[total-1][j];
115 }
116 for(int i=1; i<total; i++) {
117 for(int j=0; j<4; j++) {
118 expK[i*4 + j] = kr[i-1][j];
643 // inverse MixColumn where needed
644 for (j = 0; j < BC; j++) {
645 tt = Kd[r][j];
646 Kd[r][j] = U1[(tt >>> 24) & 0xFF] ^
647 U2[(tt >>> 16) & 0xFF] ^
648 U3[(tt >>> 8) & 0xFF] ^
649 U4[ tt & 0xFF];
650 }
651 }
652
653 // assemble the encryption (Ke) and decryption (Kd) round keys
654 // and expand them into arrays of ints.
655 int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
656 int[] expandedKd = expandToSubKey(Kd, true); // decrypting==true
657
658 ROUNDS_12 = (ROUNDS>=12);
659 ROUNDS_14 = (ROUNDS==14);
660 limit = ROUNDS*4;
661
662 // store the expanded sub keys into 'sessionK'
663 sessionK = new int[][] { expandedKe, expandedKd };
664 }
665
666
667 /**
668 * Return The number of rounds for a given Rijndael keysize.
669 *
670 * @param keySize The size of the user key material in bytes.
671 * MUST be one of (16, 24, 32).
672 * @return The number of rounds.
673 */
674 private static int getRounds(int keySize) {
675 return (keySize >> 2) + 6;
676 }
677 }
|