effbe57e创建于 2024年11月25日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
 */
package zip4cj.crypto



public class AesCipherUtil {
    private static let START_INDEX: Int64 = 0

    /**
     * Derive Password-Based Key for AES according to AE-1 and AE-2 Specifications
     *
     * @param salt Salt used for PBKDF2
     * @param password Password used for PBKDF2 containing characters matching ISO-8859-1 character set
     * @param aesKeyStrength Requested AES Key and MAC Strength
     * @return Derived Password-Based Key
     * @throws ZipException Thrown when Derived Key is not valid
     */
    public static func derivePasswordBasedKey(salt: Array<Byte> , password: Array<Rune> ,
                                                aesKeyStrength: AesKeyStrength,
                                                useUtf8ForPassword: Bool) : Array<Byte> {
        let parameters: PBKDF2Parameters = PBKDF2Parameters(InternalZipConstants.AES_MAC_ALGORITHM, InternalZipConstants.AES_HASH_CHARSET, salt, InternalZipConstants.AES_HASH_ITERATIONS)
        let engine: PBKDF2Engine = PBKDF2Engine(parameters)

        let keyLength: Int64 = aesKeyStrength.getKeyLength()
        let macLength: Int64 = aesKeyStrength.getMacLength()
        let derivedKeyLength: Int64 = keyLength + macLength + InternalZipConstants.AES_PASSWORD_VERIFIER_LENGTH
        let derivedKey: Array<Byte> = engine.deriveKey(password, derivedKeyLength, useUtf8ForPassword)
        if (derivedKey.size == derivedKeyLength) {
            return derivedKey
        } else {
            throw ZipException("Derived Key invalid for Key Length [${keyLength}] MAC Length [${macLength}]")
        }
    }

    /**
     * Derive Password Verifier using Derived Key and requested AES Key Strength
     *
     * @param derivedKey Derived Key
     * @param aesKeyStrength AES Key Strength
     * @return Derived Password Verifier
     */
    public static func derivePasswordVerifier(derivedKey: Array<Byte>, aesKeyStrength: AesKeyStrength): Array<Byte> {
        let derivedPasswordVerifier: Array<Byte> = Array<Byte>(InternalZipConstants.AES_PASSWORD_VERIFIER_LENGTH, repeat: 0)
        let keyMacLength = aesKeyStrength.getKeyLength() + aesKeyStrength.getMacLength()
        derivedKey.copyTo(derivedPasswordVerifier, keyMacLength, START_INDEX, InternalZipConstants.AES_PASSWORD_VERIFIER_LENGTH)
        return derivedPasswordVerifier
    }

    /**
     * Get MAC-Based PRF using default HMAC Algorithm defined in AE-1 and AE-2 Specification
     *
     * @param derivedKey Derived Key
     * @param aesKeyStrength AES Key Strength
     * @return Initialized MAC-Based PRF
     */
    public static func getMacBasedPRF(derivedKey: Array<Byte>, aesKeyStrength: AesKeyStrength): MacBasedPRF {
        let macLength = aesKeyStrength.getMacLength()
        let macKey: Array<Byte> = Array<Byte>(macLength, repeat: 0)
        derivedKey.copyTo(macKey, aesKeyStrength.getKeyLength(), START_INDEX, macLength)
        let macBasedPRF: MacBasedPRF = MacBasedPRF(InternalZipConstants.AES_MAC_ALGORITHM)
        macBasedPRF.initialize(macKey)
        return macBasedPRF
    }

    /**
     * Get AES Engine using derived key and requested AES Key Strength
     *
     * @param derivedKey Derived Key
     * @param aesKeyStrength AES Key Strength
     * @return AES Engine configured with AES Key
     * @throws ZipException Thrown on AESEngine initialization failures
     */
    public static func getAESEngine(derivedKey: Array<Byte>, aesKeyStrength: AesKeyStrength): AESEngine {
        let keyLength: Int64 = aesKeyStrength.getKeyLength()
        let aesKey: Array<Byte> = Array<Byte>(keyLength, repeat: 0)
        derivedKey.copyTo(aesKey, START_INDEX, START_INDEX, keyLength)
        return AESEngine(aesKey)
    }

    @OverflowWrapping
    public static func prepareBuffAESIVBytes(buff: Array<Byte>, nonce: Int64): Unit {
        buff[0] = UInt8(nonce)
        buff[1] = UInt8(nonce >> 8)
        buff[2] = UInt8(nonce >> 16)
        buff[3] = UInt8(nonce >> 24)
        for (i in 4..=15) {
            buff[i] = 0
        }
    }

}