import {describe, it, expect} from 'deccjsunit/index'
import huks from '@ohos.security.huks'
import * as Data from '../data.js';

let handle = {};
let handle1;
let handle2;
let finishData_1;
let finishData_2;
let srcData63 = Data.Date_63KB;
let srcData63Kb = stringToUint8Array(srcData63);

let HksKeyAlg = {
    HKS_ALG_PBKDF2: 52,
    HKS_ALG_AES: 20,
    HKS_ALG_DH: 103,
    HKS_ALG_HMAC: 50,
}

let HksKeyPurpose = {
    HKS_KEY_PURPOSE_AGREE: 256,
    HKS_KEY_PURPOSE_DERIVE: 16,
    HKS_KEY_PURPOSE_ENCRYPT : 1,
    HKS_KEY_PURPOSE_DECRYPT : 2,
    HKS_KEY_PURPOSE_MAC : 128,
}

let HksKeyStorageType = {
    HKS_STORAGE_TEMP: 0,
    HKS_STORAGE_PERSISTENT: 1,
};

let HksKeySize = {
    HKS_AES_KEY_SIZE_128: 128,
    HKS_AES_KEY_SIZE_192: 192,
    HKS_AES_KEY_SIZE_256: 256,
    HKS_AES_KEY_SIZE_512: 512,
    DERIVE_KEY_SIZE_32: 32
}

let HksKeyDigest = {
    HKS_DIGEST_NONE: 0,
    HKS_DIGEST_MD5: 1,
    HKS_DIGEST_SHA1: 10,
    HKS_DIGEST_SHA224: 11,
    HKS_DIGEST_SHA256: 12,
    HKS_DIGEST_SHA384: 13,
    HKS_DIGEST_SHA512: 14,
};

let HksTagType = {
    HKS_TAG_TYPE_UINT: 2 << 28,
    HKS_TAG_TYPE_BOOL: 4 << 28,
    HKS_TAG_TYPE_BYTES: 5<< 28
}

let HksCipherMode = {
    HKS_MODE_ECB: 1,
    HKS_MODE_CBC: 2,
    HKS_MODE_CTR: 3,
    HKS_MODE_OFB: 4,
    HKS_MODE_CCM: 31,
    HKS_MODE_GCM: 32,
}

let HksKeyPadding = {
    HKS_PADDING_NONE: 0,
    HKS_PADDING_OAEP: 1,
    HKS_PADDING_PSS: 2,
    HKS_PADDING_PKCS1_V1_5: 3,
    HKS_PADDING_PKCS5: 4,
    HKS_PADDING_PKCS7: 5,
}

let HksTag = {
    HKS_TAG_ALGORITHM: HksTagType.HKS_TAG_TYPE_UINT | 1,
    HKS_TAG_PURPOSE: HksTagType.HKS_TAG_TYPE_UINT | 2,
    HKS_TAG_KEY_SIZE: HksTagType.HKS_TAG_TYPE_UINT | 3,
    HKS_TAG_DIGEST: HksTagType.HKS_TAG_TYPE_UINT | 4,
	HKS_TAG_PADDING: HksTagType.HKS_TAG_TYPE_UINT | 5,
	HKS_TAG_BLOCK_MODE: HksTagType.HKS_TAG_TYPE_UINT | 6,
    HKS_TAG_DERIVE_KEY_SIZE: HksTagType.HKS_TAG_TYPE_UINT | 24,
	HKS_TAG_IS_KEY_ALIAS : HksTagType.HKS_TAG_TYPE_BOOL | 1001,
    HKS_TAG_KEY_STORAGE_FLAG: HksTagType.HKS_TAG_TYPE_UINT | 1002,
    HKS_TAG_KEY_ALIAS: HksTagType.HKS_TAG_TYPE_BYTES | 23,
}

let HuksDerive002 = {
    HuksKeySIZE: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_512 },
    HuksKeyAlgPBKDF2: { "tag": HksTag.HKS_TAG_ALGORITHM, "value": HksKeyAlg.HKS_ALG_PBKDF2 },
    HuksKeyAlgAES: { "tag": HksTag.HKS_TAG_ALGORITHM, "value": HksKeyAlg.HKS_ALG_AES },
    HuksKeyPurposePBKDF2: { "tag": HksTag.HKS_TAG_PURPOSE, "value": HksKeyPurpose.HKS_KEY_PURPOSE_DERIVE },
    HuksTagPBKDF2DigestSHA256: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA256 },
    HuksTagPBKDF2DigestSHA384: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA384 },
    HuksTagPBKDF2DigestSHA512: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA512 },
    HuksKeyPBKDF2Size128: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_128 },
    HuksKeyPBKDF2Size192: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_192 },
    HuksKeyPBKDF2Size256: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_256 },
    HuksKeyDERIVEKEYSIZE: { "tag": HksTag.HKS_TAG_DERIVE_KEY_SIZE, "value": HksKeySize.DERIVE_KEY_SIZE_32 },

	HuksKeyISKEYALIAS: { "tag": HksTag.HKS_TAG_IS_KEY_ALIAS, "value": true },
    HuksKeySTORAGE:{"tag": HksTag.HKS_TAG_KEY_STORAGE_FLAG,"value": HksKeyStorageType.HKS_STORAGE_PERSISTENT},
    HuksKeyALGORITHMAES: { "tag": HksTag.HKS_TAG_ALGORITHM, "value": HksKeyAlg.HKS_ALG_AES },
    HuksKeyALGORITHMHMAC: { "tag": HksTag.HKS_TAG_ALGORITHM, "value": HksKeyAlg.HKS_ALG_HMAC },
    HuksKeySIZE256: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_256 },
    HuksKeySIZE128: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_128 },
    HuksKeySIZE192: { "tag": HksTag.HKS_TAG_KEY_SIZE, "value": HksKeySize.HKS_AES_KEY_SIZE_192 },
    HuksKeyPurposeDERIVE: { "tag": HksTag.HKS_TAG_PURPOSE, "value": HksKeyPurpose.HKS_KEY_PURPOSE_DERIVE },
    HuksKeyPurposeMAC: { "tag": HksTag.HKS_TAG_PURPOSE, "value": HksKeyPurpose.HKS_KEY_PURPOSE_MAC },
    HuksKeyPurposeENCRYPTDECRYPT: { "tag": HksTag.HKS_TAG_PURPOSE, "value": HksKeyPurpose.HKS_KEY_PURPOSE_ENCRYPT | HksKeyPurpose.HKS_KEY_PURPOSE_DECRYPT},
    HuksKeyPADDINGNONE: { "tag": HksTag.HKS_TAG_PADDING, "value": HksKeyPadding.HKS_PADDING_NONE },
    HuksKeyPADDINGPKCS7: { "tag": HksTag.HKS_TAG_PADDING, "value": HksKeyPadding.HKS_PADDING_PKCS7 },
	HuksKeyDIGESTNONE: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_NONE},
    HuksKeyDIGESTSHA1: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA1 },
    HuksKeyDIGESTSHA224: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA224 },
    HuksKeyDIGESTSHA256: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA256 },
    HuksKeyDIGESTSHA384: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA384 },
    HuksKeyDIGESTSHA512: { "tag": HksTag.HKS_TAG_DIGEST, "value": HksKeyDigest.HKS_DIGEST_SHA512 },
    HuksKeyBLOCK_MODECBC: { "tag": HksTag.HKS_TAG_BLOCK_MODE, "value": HksCipherMode.HKS_MODE_CBC },
    HuksKeyBLOCK_MODECCM: { "tag": HksTag.HKS_TAG_BLOCK_MODE, "value": HksCipherMode.HKS_MODE_CCM },
    HuksKeyBLOCK_MODEECB: { "tag": HksTag.HKS_TAG_BLOCK_MODE, "value": HksCipherMode.HKS_MODE_ECB },
    HuksKeyBLOCK_MODECTR: { "tag": HksTag.HKS_TAG_BLOCK_MODE, "value": HksCipherMode.HKS_MODE_CTR },
    HuksKeyBLOCK_MODEGCM: { "tag": HksTag.HKS_TAG_BLOCK_MODE, "value": HksCipherMode.HKS_MODE_GCM},
}

let HuksOptions_63kb = {
	"properties": new Array(HuksDerive002.HuksKeyAlgAES, HuksDerive002.HuksKeyPurposePBKDF2, HuksDerive002.HuksTagPBKDF2DigestSHA256, HuksDerive002.HuksKeyPBKDF2Size128),
	"inData": srcData63Kb,
}

function stringToUint8Array(str) {
    var arr = [];
    for (var i = 0, j = str.length; i < j; ++i) {
        arr.push(str.charCodeAt(i));
    }
    var tmpUint8Array = new Uint8Array(arr);
    return tmpUint8Array
}

function Uint8ArrayToString(fileData){
    var dataString = "";
    for (var i = 0; i < fileData.length; i++) {
        dataString += String.fromCharCode(fileData[i]);
    }
    return dataString
}

async function publicDeriveGenFunc(srcKeyAlies, HuksOptions) {
	await huks.generateKey(srcKeyAlies, HuksOptions).then((data) => {
		console.log(`test generateKey data: ${JSON.stringify(data)}`);
		expect(data.errorCode == 0).assertTrue()
	}).catch((err) => {
		console.log("test generateKey err information: " + JSON.stringify(err))
		expect(null).assertFail();
	});
}

async function publicDeriveInitFunc(srcKeyAlies, HuksOptions) {
	await huks.init(srcKeyAlies, HuksOptions).then((data) => {
		console.log(`test init data ${JSON.stringify(data)}`);
		handle1 = data.handle1;
		handle2 = data.handle2;
		handle = {
			"handle1": handle1,
			"handle2": handle2
		};
		expect(data.errorCode == 0).assertTrue()
	}).catch((err) => {
		console.log("test init err information: " + JSON.stringify(err))
		expect(null).assertFail();
	});
}

async function publicDeriveUpdateFunc(HuksOptions) {
	await huks.update(handle, HuksOptions).then((data) => {
		console.log(`test update data ${JSON.stringify(data)}`);
		expect(data.errorCode == 0).assertTrue()
	}).catch((err) => {
		console.log("test update err information: " + JSON.stringify(err))
		expect(null).assertFail();
	});
}

async function publicDeriveFinishAbortFunc(HuksOptions_Finish, thirdInderfaceName) {
	if (thirdInderfaceName == "finish") {
		console.log(`test befor finish HuksOptions_Finish ${JSON.stringify(HuksOptions_Finish)}`);
		await huks.finish(handle, HuksOptions_Finish).then((data) => {
			console.log(`test finish data ${JSON.stringify(data)}`);
			expect(data.errorCode == 0).assertTrue()
		}).catch((err) => {
			console.log("test finish err information: " + JSON.stringify(err))
			expect(null).assertFail();
		});
	} else {
		let HuksOptions_Abort = new Array({ "tag": HksTag.HKS_TAG_KEY_STORAGE_FLAG, "value": HksKeyStorageType.HKS_STORAGE_TEMP });
		await huks.abort(handle, HuksOptions_Abort).then((data) => {
			console.log(`test abort data ${JSON.stringify(data)}`);
			expect(data.errorCode == 0).assertTrue()
		}).catch((err) => {
			console.log("test abort err information: " + JSON.stringify(err))
			expect(null).assertFail();
		});
	}
}

async function publicDeriveDeleteFunc(srcKeyAlies, HuksOptions) {
	console.log("test before deleteKey HuksOptions: " + JSON.stringify(HuksOptions));
	await huks.deleteKey(srcKeyAlies, HuksOptions).then((data) => {
		console.log(`test deleteKey data ${JSON.stringify(data)}`);
		expect(data.errorCode == 0).assertTrue()
	}).catch((err) => {
		console.log("test deleteKey err information: " + JSON.stringify(err))
		expect(null).assertFail();
	});
}

async function publicDeriveFunc(srcKeyAlies, HuksOptions, HuksOptions_Finish, thirdInderfaceName) {
	try {
		await publicDeriveGenFunc(srcKeyAlies, HuksOptions);
		HuksOptions.properties.splice(0, 1, HuksDerive002.HuksKeyAlgPBKDF2);
		HuksOptions.properties.splice(3, 1, HuksDerive002.HuksKeyDERIVEKEYSIZE);

		await publicDeriveInitFunc(srcKeyAlies,HuksOptions);
		await publicDeriveUpdateFunc(HuksOptions);
		await publicDeriveFinishAbortFunc(HuksOptions_Finish,thirdInderfaceName);

		HuksOptions.properties.splice(0, 1, HuksDerive002.HuksKeyAlgAES);
		HuksOptions.properties.splice(3, 1, HuksDerive002.HuksKeyPBKDF2Size128);
		await publicDeriveDeleteFunc(srcKeyAlies, HuksOptions);
	} catch (e) {
		expect(null).assertFail();
	}
}


describe('SecurityHuksDerivePBKDF2PromiseJsunit', function () {
	/**
     * @tc.name: testDerivePBKDF2Abort63KBDerive001
     * @tc.desc: keysize-KEY_SIZE_2048 FLAG-PERSISTENT  ALG-ALG_AES  PURPOSE-PURPOSE_ENCRYPT|PURPOSE_DECRYPT PADDING-PADDING_NONE MODE-MODE_ECB size-2048 inputdate-500kb  init>update>finish
     * @tc.type: FUNC
     */
	it('testDerivePBKDF2Abort63KBDerive001', 0, async function (done) {
		const srcKeyAlies_1 = 'testDerivePBKDF2Size128SHA256Abort63KBDeriveKeyAlias_01_001'
		let HuksOptions_Finish = {
			"properties": new Array(HuksDerive002.HuksKeySTORAGE,HuksDerive002.HuksKeyISKEYALIAS,HuksDerive002.HuksKeyALGORITHMAES,HuksDerive002.HuksKeySIZE256,HuksDerive002.HuksKeyPurposeENCRYPTDECRYPT,HuksDerive002.HuksKeyDIGESTNONE,{ "tag": HksTag.HKS_TAG_KEY_ALIAS, "value": stringToUint8Array(srcKeyAlies_1) },HuksDerive002.HuksKeyPADDINGNONE,HuksDerive002.HuksKeyBLOCK_MODEECB),
			"inData": srcData63Kb,
		}
		await publicDeriveFunc(srcKeyAlies_1, HuksOptions_63kb, HuksOptions_Finish, "abort");
		done();
	})
})