📄 umac32.java
字号:
* (b) incrementing the number by one, and (c) converting it back to 16 * bytes.</li> * * <li>If the <i>Nonce Material</i> is specified, but the <i>Key Material</i> * is not, then this implementation re-uses the previously set <i>Key * Material</i>.</li> * </ul> * * <p>This method throws an exception if no <i>Key Material</i> is specified * in the input map, and there is no previously set/defined <i>Key Material</i> * (from an earlier invocation of this method). If a <i>Key Material</i> can * be used, but no <i>Nonce Material</i> is defined or previously set/defined, * then a default value of all-zeroes shall be used.</p> * * @param attributes one or both of required parameters. * @throws InvalidKeyException the key material specified is not of the * correct length. */ public void init(Map attributes) throws InvalidKeyException, IllegalStateException { byte[] key = (byte[]) attributes.get(MAC_KEY_MATERIAL); byte[] n = (byte[]) attributes.get(NONCE_MATERIAL); boolean newKey = (key != null); boolean newNonce = (n != null); if (newKey) { if (key.length != KEY_LEN) { throw new InvalidKeyException("Key length: " + String.valueOf(key.length)); } K = key; } else { if (K == null) { throw new InvalidKeyException("Null Key"); } } if (newNonce) { if (n.length < 1 || n.length > 16) { throw new IllegalArgumentException("Invalid Nonce length: " + String.valueOf(n.length)); } if (n.length < 16) { // pad with zeroes byte[] newN = new byte[16]; System.arraycopy(n, 0, newN, 0, n.length); nonce = newN; } else { nonce = n; } nonceReuseCount = BigInteger.ZERO; } else if (nonce == null) { // use all-0 nonce if 1st time nonce = new byte[16]; nonceReuseCount = BigInteger.ZERO; } else if (!newKey) { // increment nonce if still below max count nonceReuseCount = nonceReuseCount.add(BigInteger.ONE); if (nonceReuseCount.compareTo(MAX_NONCE_ITERATIONS) >= 0) { // limit reached. we SHOULD have a key throw new InvalidKeyException("Null Key and unusable old Nonce"); } BigInteger N = new BigInteger(1, nonce); N = N.add(BigInteger.ONE).mod(MAX_NONCE_ITERATIONS); n = N.toByteArray(); if (n.length == 16) { nonce = n; } else if (n.length < 16) { nonce = new byte[16]; System.arraycopy(n, 0, nonce, 16 - n.length, n.length); } else { nonce = new byte[16]; System.arraycopy(n, n.length - 16, nonce, 0, 16); } } else { // do nothing, re-use old nonce value nonceReuseCount = BigInteger.ZERO; } if (uhash32 == null) { uhash32 = new UHash32(); } Map map = new HashMap(); map.put(MAC_KEY_MATERIAL, K); uhash32.init(map); } public void update(byte b) { uhash32.update(b); } public void update(byte[] b, int offset, int len) { uhash32.update(b, offset, len); } public byte[] digest() { byte[] result = uhash32.digest(); byte[] pad = pdf(); // pdf(K, nonce); for (int i = 0; i < OUTPUT_LEN; i++) { result[i] = (byte) (result[i] ^ pad[i]); } return result; } public void reset() { if (uhash32 != null) { uhash32.reset(); } } public boolean selfTest() { if (valid == null) { byte[] key; try { key = "abcdefghijklmnop".getBytes("ASCII"); } catch (UnsupportedEncodingException x) { throw new RuntimeException("ASCII not supported"); } byte[] nonce = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; UMac32 mac = new UMac32(); Map attributes = new HashMap(); attributes.put(MAC_KEY_MATERIAL, key); attributes.put(NONCE_MATERIAL, nonce); try { mac.init(attributes); } catch (InvalidKeyException x) { x.printStackTrace(System.err); return false; } byte[] data = new byte[128]; data[0] = (byte) 0x80; mac.update(data, 0, 128); byte[] result = mac.digest(); // System.out.println("UMAC test vector: "+Util.toString(result)); valid = new Boolean(TV1.equals(Util.toString(result))); } return valid.booleanValue(); } // helper methods ---------------------------------------------------------- /** * * @return byte array of length 8 (or OUTPUT_LEN) bytes. */ private byte[] pdf() { // Make Nonce 16 bytes by prepending zeroes. done (see init()) // one AES invocation is enough for more than one PDF invocation // number of index bits needed = 1 // Extract index bits and zero low bits of Nonce BigInteger Nonce = new BigInteger(1, nonce); int nlowbitsnum = Nonce.testBit(0) ? 1 : 0; Nonce = Nonce.clearBit(0); // Generate subkey, AES and extract indexed substring IRandom kdf = new UMacGenerator(); Map map = new HashMap(); map.put(IBlockCipher.KEY_MATERIAL, K); // map.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(128/8)); map.put(UMacGenerator.INDEX, new Integer(128)); // map.put(UMacGenerator.CIPHER, Registry.AES_CIPHER); kdf.init(map); byte[] Kp = new byte[KEY_LEN]; try { kdf.nextBytes(Kp, 0, KEY_LEN); } catch (IllegalStateException x) { x.printStackTrace(System.err); throw new RuntimeException(String.valueOf(x)); } catch (LimitReachedException x) { x.printStackTrace(System.err); throw new RuntimeException(String.valueOf(x)); } IBlockCipher aes = CipherFactory.getInstance(Registry.AES_CIPHER); map.put(IBlockCipher.KEY_MATERIAL, Kp); try { aes.init(map); } catch (InvalidKeyException x) { x.printStackTrace(System.err); throw new RuntimeException(String.valueOf(x)); } catch (IllegalStateException x) { x.printStackTrace(System.err); throw new RuntimeException(String.valueOf(x)); } byte[] T = new byte[16]; aes.encryptBlock(nonce, 0, T, 0); byte[] result = new byte[OUTPUT_LEN]; System.arraycopy(T, nlowbitsnum, result, 0, OUTPUT_LEN); return result; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -