Java版AES-CBC-CMAC加密


   /**
     * 算法邏輯
     * @param key
     * @param data
     * @return
     */
    public static byte[] Aes_Cmac01(byte[] key, byte[] data){
        // 子密鑰生成
        // 步驟1,將具有密鑰K的AES-128應用於全零輸入塊。
        byte[] L = AesEncrypt(key, new byte[16], new byte[16]);

        // 步驟2,通過以下操作得出K1:
        //如果L的最高有效位等於0,則K1是L的左移1位。
        byte[] FirstSubkey = Rol(L);
        if ((L[0] & 0x80) == 0x80) {
            // 否則,K1是const_Rb的異或和L左移1位。
            FirstSubkey[15] ^= 0x87;
        }

        // 步驟3,通過以下操作得出K2:
        //如果K1的最高有效位等於0,則K2是K1左移1位
        byte[] SecondSubkey = Rol(FirstSubkey);
        if ((FirstSubkey[0] & 0x80) == 0x80) {
            // 否則,K2是const_Rb的異或,且K1左移1位
            SecondSubkey[15] ^= 0x87;
        }


        // MAC 計算
        if (((data.length != 0) && (data.length % 16 == 0)) == true) {
            //如果輸入消息塊的大小等於塊大小(128位)
            // 最后一個塊在處理之前應與K1異或
            for (int j = 0; j < FirstSubkey.length; j++){
                data[data.length - 16 + j] ^= FirstSubkey[j];
            }

        } else {
            // 否則,最后一個塊應填充10 ^ i
            byte[] padding = new byte[16 - data.length % 16];
            padding[0] = (byte) 0x80;
            byte[] newData=new byte[data.length+padding.length];
            System.arraycopy(data,0,newData,0,data.length);
            System.arraycopy(padding,0,newData,data.length,padding.length);
            //   data = data.Concat<byte>(padding.AsEnumerable()).ToArray();
            // 並與K2進行異或運算
            for (int j = 0; j < SecondSubkey.length; j++){
                newData[newData.length - 16 + j] ^= SecondSubkey[j];
            }
            data=newData;
        }
        // 先前處理的結果將是最后一次加密的輸入。
        byte[] encResult = AesEncrypt(key, new byte[16], data);
        byte[] HashValue = new byte[16];
        System.arraycopy(encResult, encResult.length - HashValue.length, HashValue, 0, HashValue.length);

        return HashValue;
    }

    private static byte[] Rol(byte[] b)
    {
        byte[] r = new byte[b.length];
        byte carry = 0;

        for (int i = b.length - 1; i >= 0; i--)
        {
            short u = (short)(b[i] << 1);
            r[i] = (byte)((u & 0xff) + carry);
            carry = (byte)((u & 0xff00) >> 8);
        }
        return r;
    }

    /**
     * AES加密
     * @param keys
     * @param iv
     * @param data
     * @return
     */
    private static byte[] AesEncrypt(byte[] keys, byte[] iv, byte[] data)  {
        try {
            //1.根據字節數組生成AES密鑰
            SecretKey key=new SecretKeySpec(keys, "AES");
            //2.根據指定算法AES自成密碼器 "算法/模式/補碼方式"
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            //3.CBC模式需要向量vi
            IvParameterSpec ivps = new IvParameterSpec(iv);
            //4.初始化密碼器,第一個參數為加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二個參數為使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key,ivps);
            //5.獲取加密內容的字節數組(這里要設置為utf-8)不然內容中如果有中文和英文混合中文就會解密為亂碼
            byte [] byte_encode=data;
            //6.根據密碼器的初始化方式--加密:將數據加密
            byte [] byte_AES=cipher.doFinal(byte_encode);
            //7.返回
            return byte_AES;

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }

        return null;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM