diff --git a/frameworks/js/ani/BUILD.gn b/frameworks/js/ani/BUILD.gn index a8946f1a797c3a5cdf730af97cc91844472c2072..a203f23e977a0c6e9f10a5d4796946e21ef878c2 100644 --- a/frameworks/js/ani/BUILD.gn +++ b/frameworks/js/ani/BUILD.gn @@ -47,8 +47,11 @@ taihe_shared_library("crypto_framework_ani") { "${framework_path}/js/ani/src/ani_cipher.cpp", "${framework_path}/js/ani/src/ani_common.cpp", "${framework_path}/js/ani/src/ani_constructor.cpp", + "${framework_path}/js/ani/src/ani_dh_key_util.cpp", + "${framework_path}/js/ani/src/ani_ecc_key_util.cpp", "${framework_path}/js/ani/src/ani_kdf.cpp", "${framework_path}/js/ani/src/ani_key.cpp", + "${framework_path}/js/ani/src/ani_key_agreement.cpp", "${framework_path}/js/ani/src/ani_key_pair.cpp", "${framework_path}/js/ani/src/ani_mac.cpp", "${framework_path}/js/ani/src/ani_md.cpp", @@ -56,6 +59,7 @@ taihe_shared_library("crypto_framework_ani") { "${framework_path}/js/ani/src/ani_pub_key.cpp", "${framework_path}/js/ani/src/ani_rand.cpp", "${framework_path}/js/ani/src/ani_sign.cpp", + "${framework_path}/js/ani/src/ani_sm2_crypto_util.cpp", "${framework_path}/js/ani/src/ani_sym_key.cpp", "${framework_path}/js/ani/src/ani_sym_key_generator.cpp", "${framework_path}/js/ani/src/ani_verify.cpp", diff --git a/frameworks/js/ani/idl/ohos.security.cryptoFramework.cryptoFramework.taihe b/frameworks/js/ani/idl/ohos.security.cryptoFramework.cryptoFramework.taihe index 56cd6a362c60e71115be7c7194fd8f3427dbb077..d5d29fa8175e7366fdf082f58b5e46905edc2b69 100644 --- a/frameworks/js/ani/idl/ohos.security.cryptoFramework.cryptoFramework.taihe +++ b/frameworks/js/ani/idl/ohos.security.cryptoFramework.cryptoFramework.taihe @@ -69,6 +69,26 @@ interface Random { } function CreateRandom(): Random; +struct MacSpec { + algName: String; +} + +struct HmacSpec { + @extends base: MacSpec; + mdName: String; +} + +struct CmacSpec { + @extends base: MacSpec; + cipherName: String; +} + +union OptExtMacSpec { + HMACSPEC: HmacSpec; + CMACSPEC: CmacSpec; + MACSPEC: MacSpec; +} + interface Mac { @gen_async("init") @gen_promise("init") @@ -82,7 +102,10 @@ interface Mac { GetMacLength(): i32; @get("algName") GetAlgName(): String; } +@overload("createMac") function CreateMac(algName: String): Mac; +@overload("createMac") +function CreateMacBySpec(macSpec: OptExtMacSpec): Mac; interface Key { GetKeyObj(): i64; @@ -131,6 +154,14 @@ enum AsyKeySpecEnum: i32 { X25519_PK_BN = 602 } +enum CipherSpecEnum: i32 { + OAEP_MD_NAME_STR = 100, + OAEP_MGF_NAME_STR = 101, + OAEP_MGF1_MD_STR = 102, + OAEP_MGF1_PSRC_UINT8ARR = 103, + SM2_MD_NAME_STR = 104 +} + enum SignSpecEnum: i32 { PSS_MD_NAME_STR = 100, PSS_MGF_NAME_STR = 101, @@ -156,7 +187,10 @@ interface PriKey: Key { ClearMem(): void; GetAsyKeySpec(itemType: AsyKeySpecEnum): OptKeySpec; GetEncodedDer(format: String): DataBlob; - GetEncodedPem(format: String, config: Optional): String; + @overload("getEncodedPem") + GetEncodedPem(format: String): String; + @overload("getEncodedPem") + GetEncodedPemEx(format: String, config: KeyEncodingConfig): String; } interface PubKey: Key { @@ -197,9 +231,14 @@ interface AsyKeyGenerator { @gen_async("convertKey") @gen_promise("convertKey") ConvertKeySync(pubKey: OptDataBlob, priKey: OptDataBlob): KeyPair; - @gen_async("convertKeySync") - @gen_promise("convertKeySync") - ConvertPemKeySync(pubKey: OptString, priKey: OptString, password: Optional): KeyPair; + @gen_async("convertPemKey") + @gen_promise("convertPemKey") + @overload("convertPemKeySync") + ConvertPemKeySync(pubKey: OptString, priKey: OptString): KeyPair; + @gen_async("convertPemKey") + @gen_promise("convertPemKey") + @overload("convertPemKeySync") + ConvertPemKeySyncEx(pubKey: OptString, priKey: OptString, password: String): KeyPair; @get("algName") GetAlgName(): String; } function CreateAsyKeyGenerator(algName: String): AsyKeyGenerator; @@ -300,6 +339,8 @@ interface Cipher { @gen_async("doFinal") @gen_promise("doFinal") DoFinalSync(input: OptDataBlob): DataBlob; + SetCipherSpec(itemType: CipherSpecEnum, itemValue: @typedarray Array): void; + GetCipherSpec(itemType: CipherSpecEnum): OptStrUint8Arr; @get("algName") GetAlgName(): String; } function CreateCipher(transformation: String): Cipher; @@ -370,10 +411,6 @@ struct DSAAsyKeySpec { sk: @bigint Array; } -struct ECCField { - fieldType: String; -} - struct Point { x: @bigint Array; y: @bigint Array; @@ -501,7 +538,7 @@ struct ECFieldFp { union OptECField { ECFIELDFP: ECFieldFp; - ECFIELD: ECCField; + ECFIELD: ECField; } union OptAsyKeySpec { @@ -541,3 +578,42 @@ interface AsyKeyGeneratorBySpec { @get("algName") GetAlgName(): String; } function CreateAsyKeyGeneratorBySpec(asyKeySpec: OptAsyKeySpec): AsyKeyGeneratorBySpec; + +interface KeyAgreement { + @gen_async("generateSecret") + @gen_promise("generateSecret") + GenerateSecretSync(priKey: PriKey, pubKey: PubKey): DataBlob; + @get("algName") GetAlgName(): String; +} +function CreateKeyAgreement(algName: String): KeyAgreement; + +@class +interface DHKeyUtil { +} +@static("DHKeyUtil") +function GenDHCommonParamsSpec(pLen: i32, skLen: Optional): DHCommonParamsSpec; + +@class +interface ECCKeyUtil { +} +@static("ECCKeyUtil") +function GenECCCommonParamsSpec(curveName: String): ECCCommonParamsSpec; +@static("ECCKeyUtil") +function ConvertPoint(curveName: String, encodedPoint: @typedarray Array): Point; +@static("ECCKeyUtil") +function GetEncodedPoint(curveName: String, point: Point, format: String): @typedarray Array; + +struct SM2CipherTextSpec { + xCoordinate: @bigint Array; + yCoordinate: @bigint Array; + cipherTextData: @typedarray Array; + hashData: @typedarray Array; +} + +@class +interface SM2CryptoUtil { +} +@static("SM2CryptoUtil") +function GenCipherTextBySpec(spec: SM2CipherTextSpec, mode: Optional): DataBlob; +@static("SM2CryptoUtil") +function GetCipherTextSpec(cipherText: DataBlob, mode: Optional): SM2CipherTextSpec; diff --git a/frameworks/js/ani/inc/ani_asy_key_generator.h b/frameworks/js/ani/inc/ani_asy_key_generator.h index b9a41571592a891a87ace4fb9e2351793875a51a..8b5eba6b1a1f7223ef60382612d47573de5a3f9a 100644 --- a/frameworks/js/ani/inc/ani_asy_key_generator.h +++ b/frameworks/js/ani/inc/ani_asy_key_generator.h @@ -28,7 +28,8 @@ public: KeyPair GenerateKeyPairSync(); KeyPair ConvertKeySync(OptDataBlob const& pubKey, OptDataBlob const& priKey); - KeyPair ConvertPemKeySync(OptString const& pubKey, OptString const& priKey, optional_view password); + KeyPair ConvertPemKeySync(OptString const& pubKey, OptString const& priKey); + KeyPair ConvertPemKeySyncEx(OptString const& pubKey, OptString const& priKey, string_view password); string GetAlgName(); private: diff --git a/frameworks/js/ani/inc/ani_cipher.h b/frameworks/js/ani/inc/ani_cipher.h index 593fec558316442545f83132d39645482f368334..8cfade552e62aa09f3a227a7c3fa345fc092e29b 100644 --- a/frameworks/js/ani/inc/ani_cipher.h +++ b/frameworks/js/ani/inc/ani_cipher.h @@ -29,6 +29,8 @@ public: void InitSync(CryptoMode opMode, weak::Key key, OptParamsSpec const& params); DataBlob UpdateSync(DataBlob const& input); DataBlob DoFinalSync(OptDataBlob const& input); + void SetCipherSpec(CipherSpecEnum itemType, array_view itemValue); + OptStrUint8Arr GetCipherSpec(CipherSpecEnum itemType); string GetAlgName(); private: diff --git a/frameworks/js/ani/inc/ani_common.h b/frameworks/js/ani/inc/ani_common.h index 1e09036eee28a8dae8ce9870d403f92c6b7827b0..27b50543fffa12df788cdb14130c13cd6a2b440e 100644 --- a/frameworks/js/ani/inc/ani_common.h +++ b/frameworks/js/ani/inc/ani_common.h @@ -32,18 +32,21 @@ namespace ANI::CryptoFramework { using namespace taihe; using namespace ohos::security::cryptoFramework::cryptoFramework; -template -void ArrayU8ToDataBlob(const array &arr, T &blob); - -void StringToDataBlob(const string &str, HcfBlob &blob); - -int ConvertResultCode(HcfResult res); - #define ANI_LOGE_THROW(code, msg) \ do { \ LOGE(msg); \ set_business_error(ConvertResultCode(code), msg); \ } while (0) + +int ConvertResultCode(HcfResult res); + +template +void ArrayU8ToDataBlob(const array &arr, T &blob); + +template +void DataBlobToArrayU8(const T &blob, array &arr); + +void StringToDataBlob(const string &str, HcfBlob &blob); } // namespace ANI::CryptoFramework #endif // ANI_COMMON_H diff --git a/frameworks/js/ani/inc/ani_dh_key_util.h b/frameworks/js/ani/inc/ani_dh_key_util.h new file mode 100644 index 0000000000000000000000000000000000000000..eac9149dd4e2f47add707f18d8c065e16e210576 --- /dev/null +++ b/frameworks/js/ani/inc/ani_dh_key_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_DH_KEY_UTIL_H +#define ANI_DH_KEY_UTIL_H + +#include "ani_common.h" + +namespace ANI::CryptoFramework { +class DHKeyUtilImpl { +public: + DHKeyUtilImpl() = delete; + ~DHKeyUtilImpl() = delete; +}; +} // namespace ANI::CryptoFramework + +#endif // ANI_DH_KEY_UTIL_H diff --git a/frameworks/js/ani/inc/ani_ecc_key_util.h b/frameworks/js/ani/inc/ani_ecc_key_util.h new file mode 100644 index 0000000000000000000000000000000000000000..ccb22eb847c057529fd6000b829a3668ed40e46a --- /dev/null +++ b/frameworks/js/ani/inc/ani_ecc_key_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_ECC_KEY_UTIL_H +#define ANI_ECC_KEY_UTIL_H + +#include "ani_common.h" + +namespace ANI::CryptoFramework { +class ECCKeyUtilImpl { +public: + ECCKeyUtilImpl() = delete; + ~ECCKeyUtilImpl() = delete; +}; +} // namespace ANI::CryptoFramework + +#endif // ANI_ECC_KEY_UTIL_H diff --git a/frameworks/js/ani/inc/ani_key_agreement.h b/frameworks/js/ani/inc/ani_key_agreement.h new file mode 100644 index 0000000000000000000000000000000000000000..d21fdf492714bc4a517151bffe0783b43d2c861c --- /dev/null +++ b/frameworks/js/ani/inc/ani_key_agreement.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_KEY_AGREEMENT_H +#define ANI_KEY_AGREEMENT_H + +#include "ani_common.h" +#include "key_agreement.h" + +namespace ANI::CryptoFramework { +class KeyAgreementImpl { +public: + KeyAgreementImpl(); + explicit KeyAgreementImpl(HcfKeyAgreement *keyAgreement); + ~KeyAgreementImpl(); + + DataBlob GenerateSecretSync(weak::PriKey priKey, weak::PubKey pubKey); + string GetAlgName(); + +private: + HcfKeyAgreement *keyAgreement_ = nullptr; +}; +} // namespace ANI::CryptoFramework + +#endif // ANI_KEY_AGREEMENT_H diff --git a/frameworks/js/ani/inc/ani_pri_key.h b/frameworks/js/ani/inc/ani_pri_key.h index 1947df81b8204e0e7eafa05cfa80f9f31866758b..802f40776286c7f4b6149646fab4f67a6f3cb646 100644 --- a/frameworks/js/ani/inc/ani_pri_key.h +++ b/frameworks/js/ani/inc/ani_pri_key.h @@ -30,7 +30,8 @@ public: void ClearMem(); OptKeySpec GetAsyKeySpec(AsyKeySpecEnum itemType); DataBlob GetEncodedDer(string_view format); - string GetEncodedPem(string_view format, optional_view config); + string GetEncodedPem(string_view format); + string GetEncodedPemEx(string_view format, KeyEncodingConfig const& config); int64_t GetKeyObj(); DataBlob GetEncoded(); string GetFormat(); diff --git a/frameworks/js/ani/inc/ani_sm2_crypto_util.h b/frameworks/js/ani/inc/ani_sm2_crypto_util.h new file mode 100644 index 0000000000000000000000000000000000000000..88a96ccfac362c8c47bdf8317c6f8666f6d029ff --- /dev/null +++ b/frameworks/js/ani/inc/ani_sm2_crypto_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANI_SM2_CRYPTO_UTIL_H +#define ANI_SM2_CRYPTO_UTIL_H + +#include "ani_common.h" + +namespace ANI::CryptoFramework { +class SM2CryptoUtilImpl { +public: + SM2CryptoUtilImpl() = delete; + ~SM2CryptoUtilImpl() = delete; +}; +} // namespace ANI::CryptoFramework + +#endif // ANI_SM2_CRYPTO_UTIL_H diff --git a/frameworks/js/ani/inc/ani_verify.h b/frameworks/js/ani/inc/ani_verify.h index 94af0a28e35df8756a73a61f658ca9dd22fd4e5e..aeedbcc8bbb34b04cc3ce8e0c4552ed755d48c55 100644 --- a/frameworks/js/ani/inc/ani_verify.h +++ b/frameworks/js/ani/inc/ani_verify.h @@ -23,7 +23,7 @@ namespace ANI::CryptoFramework { class VerifyImpl { public: VerifyImpl(); - explicit VerifyImpl(HcfVerify *obj); + explicit VerifyImpl(HcfVerify *verify); ~VerifyImpl(); void InitSync(weak::PubKey pubKey); diff --git a/frameworks/js/ani/src/ani_asy_key_generator.cpp b/frameworks/js/ani/src/ani_asy_key_generator.cpp index 1f64ce406eb1853f1d6b0952d1a62fbd242308e5..d9d99ff9216d5c7faeec65d8f8053c5442e410f7 100644 --- a/frameworks/js/ani/src/ani_asy_key_generator.cpp +++ b/frameworks/js/ani/src/ani_asy_key_generator.cpp @@ -16,6 +16,34 @@ #include "ani_asy_key_generator.h" #include "ani_key_pair.h" +namespace { +using namespace ANI::CryptoFramework; + +KeyPair ConvertPemKeyInner(HcfAsyKeyGenerator *self, HcfParamsSpec *spec, + OptString const& pubKey, OptString const& priKey) +{ + if (self == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "generator obj is nullptr!"); + return make_holder(); + } + const char *pkStr = nullptr; + const char *skStr = nullptr; + if (pubKey.get_tag() == OptString::tag_t::STRING) { + pkStr = pubKey.get_STRING_ref().c_str(); + } + if (priKey.get_tag() == OptString::tag_t::STRING) { + skStr = priKey.get_STRING_ref().c_str(); + } + HcfKeyPair *keyPair = nullptr; + HcfResult res = self->convertPemKey(self, spec, pkStr, skStr, &keyPair); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "convert pem key fail."); + return make_holder(); + } + return make_holder(keyPair); +} +} // namespace + namespace ANI::CryptoFramework { AsyKeyGeneratorImpl::AsyKeyGeneratorImpl() {} @@ -61,7 +89,7 @@ KeyPair AsyKeyGeneratorImpl::ConvertKeySync(OptDataBlob const& pubKey, OptDataBl ArrayU8ToDataBlob(priKey.get_DATABLOB_ref().data, skBlob); priKeyBlob = &skBlob; } - HcfResult res = this->generator_->convertKey(this->generator_, nullptr, pubKeyBlob, priKeyBlob, &(keyPair)); + HcfResult res = this->generator_->convertKey(this->generator_, nullptr, pubKeyBlob, priKeyBlob, &keyPair); if (res != HCF_SUCCESS) { ANI_LOGE_THROW(res, "convert key fail."); return make_holder(); @@ -69,12 +97,16 @@ KeyPair AsyKeyGeneratorImpl::ConvertKeySync(OptDataBlob const& pubKey, OptDataBl return make_holder(keyPair); } -KeyPair AsyKeyGeneratorImpl::ConvertPemKeySync(OptString const& pubKey, - OptString const& priKey, optional_view password) +KeyPair AsyKeyGeneratorImpl::ConvertPemKeySync(OptString const& pubKey, OptString const& priKey) +{ + return ConvertPemKeyInner(this->generator_, nullptr, pubKey, priKey); +} + +KeyPair AsyKeyGeneratorImpl::ConvertPemKeySyncEx(OptString const& pubKey, OptString const& priKey, string_view password) { - // The parameters in the make_holder function should be of the same type - // as the parameters in the constructor of the actual implementation class. - return make_holder(); + HcfKeyDecodingParamsSpec spec = {}; + spec.password = const_cast(password.c_str()); + return ConvertPemKeyInner(this->generator_, reinterpret_cast(&spec), pubKey, priKey); } string AsyKeyGeneratorImpl::GetAlgName() diff --git a/frameworks/js/ani/src/ani_cipher.cpp b/frameworks/js/ani/src/ani_cipher.cpp index 943da4ac22dbfcfe8c5a7fc9fd650bdeac5ba364..026baed48b4083ccaa20093584caa95f67852ae6 100644 --- a/frameworks/js/ani/src/ani_cipher.cpp +++ b/frameworks/js/ani/src/ani_cipher.cpp @@ -101,8 +101,9 @@ void CipherImpl::InitSync(CryptoMode opMode, weak::Key key, OptParamsSpec const& return; } } - HcfKey *obj = reinterpret_cast(key->GetKeyObj()); - HcfResult res = this->cipher_->init(this->cipher_, static_cast(opMode.get_value()), obj, paramsSpec); + HcfKey *hcfKey = reinterpret_cast(key->GetKeyObj()); + HcfResult res = this->cipher_->init(this->cipher_, static_cast(opMode.get_value()), + hcfKey, paramsSpec); if (res != HCF_SUCCESS) { ANI_LOGE_THROW(res, "init cipher fail."); return; @@ -123,7 +124,8 @@ DataBlob CipherImpl::UpdateSync(DataBlob const& input) ANI_LOGE_THROW(res, "cipher update failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } @@ -146,11 +148,22 @@ DataBlob CipherImpl::DoFinalSync(OptDataBlob const& input) ANI_LOGE_THROW(res, "cipher doFinal failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } +void CipherImpl::SetCipherSpec(CipherSpecEnum itemType, array_view itemValue) +{ + TH_THROW(std::runtime_error, "SetCipherSpec not implemented"); +} + +OptStrUint8Arr CipherImpl::GetCipherSpec(CipherSpecEnum itemType) +{ + TH_THROW(std::runtime_error, "GetCipherSpec not implemented"); +} + string CipherImpl::GetAlgName() { if (this->cipher_ == nullptr) { diff --git a/frameworks/js/ani/src/ani_common.cpp b/frameworks/js/ani/src/ani_common.cpp index ef59e97247ada41deeecaacf20ce68d845edc663..277a56124149ab002fd4e41485b170afbd8cd426 100644 --- a/frameworks/js/ani/src/ani_common.cpp +++ b/frameworks/js/ani/src/ani_common.cpp @@ -28,6 +28,21 @@ enum ResultCode { } // namespace namespace ANI::CryptoFramework { +int ConvertResultCode(HcfResult res) +{ + static std::unordered_map resCodeMap = { + { HCF_SUCCESS, SUCCESS }, + { HCF_INVALID_PARAMS, INVALID_PARAMS }, + { HCF_NOT_SUPPORT, NOT_SUPPORT }, + { HCF_ERR_MALLOC, ERR_OUT_OF_MEMORY }, + { HCF_ERR_CRYPTO_OPERATION, ERR_CRYPTO_OPERATION } + }; + if (resCodeMap.count(res) > 0) { + return resCodeMap[res]; + } + return ERR_RUNTIME_ERROR; +} + template void ArrayU8ToDataBlob(const array &arr, HcfBlob &blob); template void ArrayU8ToDataBlob(const array &arr, HcfBigInteger &blob); @@ -38,24 +53,24 @@ void ArrayU8ToDataBlob(const array &arr, T &blob) blob.len = arr.size(); } -void StringToDataBlob(const string &str, HcfBlob &blob) +template<> +void DataBlobToArrayU8(const HcfBlob &blob, array &arr) { - blob.data = str.empty() ? nullptr : reinterpret_cast(const_cast(str.c_str())); - blob.len = str.size(); + arr = array(move_data_t{}, blob.data, blob.len); } -int ConvertResultCode(HcfResult res) +template<> +void DataBlobToArrayU8(const HcfBigInteger &blob, array &arr) { - static std::unordered_map resCodeMap = { - { HCF_SUCCESS, SUCCESS }, - { HCF_INVALID_PARAMS, INVALID_PARAMS }, - { HCF_NOT_SUPPORT, NOT_SUPPORT }, - { HCF_ERR_MALLOC, ERR_OUT_OF_MEMORY }, - { HCF_ERR_CRYPTO_OPERATION, ERR_CRYPTO_OPERATION } - }; - if (resCodeMap.count(res) > 0) { - return resCodeMap[res]; - } - return ERR_RUNTIME_ERROR; + arr = array(blob.len + 1); + std::copy(blob.data, blob.data + blob.len, arr.data()); + // 0x00 is the sign bit of big integer, it's always a positive number in this implementation + arr[blob.len] = 0x00; +} + +void StringToDataBlob(const string &str, HcfBlob &blob) +{ + blob.data = str.empty() ? nullptr : reinterpret_cast(const_cast(str.c_str())); + blob.len = str.size(); } } // namespace ANI::CryptoFramework diff --git a/frameworks/js/ani/src/ani_dh_key_util.cpp b/frameworks/js/ani/src/ani_dh_key_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..784260b9721f4e7736b4f72a5d894a474273b720 --- /dev/null +++ b/frameworks/js/ani/src/ani_dh_key_util.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_dh_key_util.h" +#include "dh_key_util.h" +#include "detailed_dh_key_params.h" + +namespace ANI::CryptoFramework { +DHCommonParamsSpec GenDHCommonParamsSpec(int32_t pLen, optional_view skLen) +{ + DHCommonParamsSpec dh = { + .base = { + .specType = AsyKeySpecType::key_t::COMMON_PARAMS_SPEC + } + }; + int32_t skLenValue = skLen.has_value() ? skLen.value() : 0; + HcfDhCommParamsSpec *dhCommParamsSpec = nullptr; + HcfResult res = HcfDhKeyUtilCreate(pLen, skLenValue, &dhCommParamsSpec); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "create C dhKey obj fail!"); + return dh; + } + dh.base.algName = string(dhCommParamsSpec->base.algName); + dh.base.specType = AsyKeySpecType(static_cast(dhCommParamsSpec->base.specType)); + dh.l = dhCommParamsSpec->length; + DataBlobToArrayU8(dhCommParamsSpec->p, dh.p); + DataBlobToArrayU8(dhCommParamsSpec->g, dh.g); + HcfObjDestroy(dhCommParamsSpec); + return dh; +} +} // namespace ANI::CryptoFramework + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_GenDHCommonParamsSpec(ANI::CryptoFramework::GenDHCommonParamsSpec); +// NOLINTEND diff --git a/frameworks/js/ani/src/ani_ecc_key_util.cpp b/frameworks/js/ani/src/ani_ecc_key_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..203b64daa3738beb16783f3454377d73b84d25ef --- /dev/null +++ b/frameworks/js/ani/src/ani_ecc_key_util.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ani_ecc_key_util.h" +#include "detailed_ecc_key_params.h" +#include "ecc_key_util.h" + +namespace ANI::CryptoFramework { +ECCCommonParamsSpec GenECCCommonParamsSpec(string_view curveName) +{ + ECFieldFp ecFieldFp = {}; + ECCCommonParamsSpec ecc = { + .base = { + .specType = AsyKeySpecType::key_t::COMMON_PARAMS_SPEC, + }, + .field = OptECField::make_ECFIELDFP(ecFieldFp) + }; + HcfEccCommParamsSpec *eccCommParamsSpec = nullptr; + HcfResult res = HcfEccKeyUtilCreate(curveName.c_str(), &eccCommParamsSpec); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "create C eccKey obj fail!"); + return ecc; + } + HcfECFieldFp *tmp = reinterpret_cast(eccCommParamsSpec->field); + ecFieldFp.base.fieldType = string(tmp->base.fieldType); + DataBlobToArrayU8(tmp->p, ecFieldFp.p); + ecc.field = OptECField::make_ECFIELDFP(ecFieldFp); + ecc.base.algName = string(eccCommParamsSpec->base.algName); + ecc.base.specType = AsyKeySpecType(static_cast(eccCommParamsSpec->base.specType)); + ecc.h = eccCommParamsSpec->h; + DataBlobToArrayU8(eccCommParamsSpec->a, ecc.a); + DataBlobToArrayU8(eccCommParamsSpec->b, ecc.b); + DataBlobToArrayU8(eccCommParamsSpec->g.x, ecc.g.x); + DataBlobToArrayU8(eccCommParamsSpec->g.y, ecc.g.y); + DataBlobToArrayU8(eccCommParamsSpec->n, ecc.n); + HcfObjDestroy(eccCommParamsSpec); + return ecc; +} + +Point ConvertPoint(string_view curveName, array_view encodedPoint) +{ + HcfPoint hcfPoint = {}; + HcfBlob pointBlob = {}; + ArrayU8ToDataBlob(encodedPoint, pointBlob); + HcfResult res = HcfConvertPoint(curveName.c_str(), &pointBlob, &hcfPoint); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "failed to convert point."); + return {}; + } + Point point = {}; + DataBlobToArrayU8(hcfPoint.x, point.x); + DataBlobToArrayU8(hcfPoint.y, point.y); + FreeEcPointMem(&hcfPoint); + return point; +} + +array GetEncodedPoint(string_view curveName, Point const& point, string_view format) +{ + HcfPoint hcfPoint = {}; + ArrayU8ToDataBlob(point.x, hcfPoint.x); + ArrayU8ToDataBlob(point.y, hcfPoint.y); + HcfBlob outBlob = {}; + HcfResult res = HcfGetEncodedPoint(curveName.c_str(), &hcfPoint, format.c_str(), &outBlob); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "fail to get point data."); + return {}; + } + array data = {}; + DataBlobToArrayU8(outBlob, data); + HcfBlobDataClearAndFree(&outBlob); + return data; +} +} // namespace ANI::CryptoFramework + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_GenECCCommonParamsSpec(ANI::CryptoFramework::GenECCCommonParamsSpec); +TH_EXPORT_CPP_API_ConvertPoint(ANI::CryptoFramework::ConvertPoint); +TH_EXPORT_CPP_API_GetEncodedPoint(ANI::CryptoFramework::GetEncodedPoint); +// NOLINTEND diff --git a/frameworks/js/ani/src/ani_kdf.cpp b/frameworks/js/ani/src/ani_kdf.cpp index 2a1df58bc3f6efc86d27dfb7b1be920083dcac2e..5c6c5ff9628bedfe52964b6cf0d96220ddad8b38 100644 --- a/frameworks/js/ani/src/ani_kdf.cpp +++ b/frameworks/js/ani/src/ani_kdf.cpp @@ -118,7 +118,8 @@ DataBlob KdfImpl::GenerateSecretSync(OptExtKdfSpec const& params) ANI_LOGE_THROW(res, "kdf generateSecret failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_key.cpp b/frameworks/js/ani/src/ani_key.cpp index 33aa6d1b47f874c3bf074619f84d2d5f56064691..cb15e66c339e97cd7b90a86024846c91aba60b36 100644 --- a/frameworks/js/ani/src/ani_key.cpp +++ b/frameworks/js/ani/src/ani_key.cpp @@ -43,7 +43,8 @@ DataBlob KeyImpl::GetEncoded() ANI_LOGE_THROW(res, "getEncoded failed."); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_key_agreement.cpp b/frameworks/js/ani/src/ani_key_agreement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a33fe5bdfddc5c6e203e1ad2734b95cb9ff77c9 --- /dev/null +++ b/frameworks/js/ani/src/ani_key_agreement.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_key_agreement.h" + +namespace ANI::CryptoFramework { +KeyAgreementImpl::KeyAgreementImpl() {} + +KeyAgreementImpl::KeyAgreementImpl(HcfKeyAgreement *keyAgreement) : keyAgreement_(keyAgreement) {} + +KeyAgreementImpl::~KeyAgreementImpl() +{ + HcfObjDestroy(this->keyAgreement_); + this->keyAgreement_ = nullptr; +} + +DataBlob KeyAgreementImpl::GenerateSecretSync(weak::PriKey priKey, weak::PubKey pubKey) +{ + if (this->keyAgreement_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "keyAgreement obj is nullptr!"); + return {}; + } + HcfPriKey *hcfPriKey = reinterpret_cast(priKey->GetPriKeyObj()); + HcfPubKey *hcfPubKey = reinterpret_cast(pubKey->GetPubKeyObj()); + HcfBlob outBlob = {}; + HcfResult res = this->keyAgreement_->generateSecret(this->keyAgreement_, hcfPriKey, hcfPubKey, &outBlob); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "keyAgreement generateSecret fail."); + return {}; + } + array data = {}; + DataBlobToArrayU8(outBlob, data); + HcfBlobDataClearAndFree(&outBlob); + return { data }; +} + +string KeyAgreementImpl::GetAlgName() +{ + if (this->keyAgreement_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "keyAgreement obj is nullptr!"); + return ""; + } + const char *algName = this->keyAgreement_->getAlgoName(this->keyAgreement_); + return (algName == nullptr) ? "" : string(algName); +} + +KeyAgreement CreateKeyAgreement(string_view algName) +{ + HcfKeyAgreement *keyAgreement = nullptr; + HcfResult res = HcfKeyAgreementCreate(algName.c_str(), &keyAgreement); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "create c keyAgreement obj fail."); + return make_holder(); + } + return make_holder(keyAgreement); +} +} // namespace ANI::CryptoFramework + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_CreateKeyAgreement(ANI::CryptoFramework::CreateKeyAgreement); +// NOLINTEND diff --git a/frameworks/js/ani/src/ani_mac.cpp b/frameworks/js/ani/src/ani_mac.cpp index a8843dc1a3ac6bab47c8dda43ba5c1247a640569..1326a93314a285ab3a5471ee63ee4132105d199f 100644 --- a/frameworks/js/ani/src/ani_mac.cpp +++ b/frameworks/js/ani/src/ani_mac.cpp @@ -15,6 +15,25 @@ #include "ani_mac.h" #include "detailed_hmac_params.h" +#include "detailed_cmac_params.h" + +namespace { +using namespace ANI::CryptoFramework; + +const std::string HMAC_ALG_NAME = "HMAC"; +const std::string CMAC_ALG_NAME = "CMAC"; + +Mac CreateMacInner(HcfMacParamsSpec *spec) +{ + HcfMac *mac = nullptr; + HcfResult res = HcfMacCreate(spec, &mac); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "create C mac obj failed."); + return make_holder(); + } + return make_holder(mac); +} +} // namespace namespace ANI::CryptoFramework { MacImpl::MacImpl() {} @@ -33,8 +52,8 @@ void MacImpl::InitSync(weak::SymKey key) ANI_LOGE_THROW(HCF_INVALID_PARAMS, "mac obj is nullptr!"); return; } - HcfSymKey *obj = reinterpret_cast(key->GetSymKeyObj()); - HcfResult res = this->mac_->init(this->mac_, obj); + HcfSymKey *hcfSymKey = reinterpret_cast(key->GetSymKeyObj()); + HcfResult res = this->mac_->init(this->mac_, hcfSymKey); if (res != HCF_SUCCESS) { ANI_LOGE_THROW(res, "mac init failed!"); return; @@ -68,7 +87,8 @@ DataBlob MacImpl::DoFinalSync() ANI_LOGE_THROW(res, "mac doFinal failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } @@ -95,18 +115,36 @@ string MacImpl::GetAlgName() Mac CreateMac(string_view algName) { - HcfMac *mac = nullptr; - HcfHmacParamsSpec parmas = { { "HMAC" }, algName.c_str() }; - HcfResult res = HcfMacCreate(reinterpret_cast(&parmas), &mac); - if (res != HCF_SUCCESS) { - ANI_LOGE_THROW(res, "create C mac obj failed."); + HcfHmacParamsSpec spec = {}; + spec.base.algName = HMAC_ALG_NAME.c_str(); + spec.mdName = algName.c_str(); + return CreateMacInner(reinterpret_cast(&spec)); +} + +Mac CreateMacBySpec(OptExtMacSpec const& macSpec) +{ + HcfMacParamsSpec *spec = nullptr; + HcfHmacParamsSpec hmacSpec = {}; + HcfCmacParamsSpec cmacSpec = {}; + const std::string &algName = macSpec.get_MACSPEC_ref().algName.c_str(); + if (macSpec.get_tag() == OptExtMacSpec::tag_t::HMACSPEC && algName == HMAC_ALG_NAME) { + hmacSpec.base.algName = algName.c_str(); + hmacSpec.mdName = macSpec.get_HMACSPEC_ref().mdName.c_str(); + spec = reinterpret_cast(&hmacSpec); + } else if (macSpec.get_tag() == OptExtMacSpec::tag_t::CMACSPEC && algName == CMAC_ALG_NAME) { + cmacSpec.base.algName = algName.c_str(); + cmacSpec.cipherName = macSpec.get_CMACSPEC_ref().cipherName.c_str(); + spec = reinterpret_cast(&cmacSpec); + } else { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "invalid mac spec!"); return make_holder(); } - return make_holder(mac); + return CreateMacInner(spec); } } // namespace ANI::CryptoFramework // Since these macros are auto-generate, lint will cause false positive. // NOLINTBEGIN TH_EXPORT_CPP_API_CreateMac(ANI::CryptoFramework::CreateMac); +TH_EXPORT_CPP_API_CreateMacBySpec(ANI::CryptoFramework::CreateMacBySpec); // NOLINTEND diff --git a/frameworks/js/ani/src/ani_md.cpp b/frameworks/js/ani/src/ani_md.cpp index c9e5856280b9d3652c02c71f5f76201fbee360f9..60020f8f203b02b3eaec9efbb3c1a0bdce914928 100644 --- a/frameworks/js/ani/src/ani_md.cpp +++ b/frameworks/js/ani/src/ani_md.cpp @@ -53,7 +53,8 @@ DataBlob MdImpl::DigestSync() ANI_LOGE_THROW(res, "mac doFinal failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_pri_key.cpp b/frameworks/js/ani/src/ani_pri_key.cpp index 8a0da4c57286b4ea576b623a616c3db1daa559d1..1ce99ddbc7702d6f1c7e5dc0a5d408cec6ce9146 100644 --- a/frameworks/js/ani/src/ani_pri_key.cpp +++ b/frameworks/js/ani/src/ani_pri_key.cpp @@ -15,6 +15,27 @@ #include "ani_pri_key.h" +namespace { +using namespace ANI::CryptoFramework; + +string GetEncodedPemInner(const HcfPriKey *self, HcfParamsSpec *params, string_view format) +{ + if (self == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "priKey obj is nullptr!"); + return ""; + } + char *encoded = nullptr; + HcfResult res = self->getEncodedPem(self, params, format.c_str(), &encoded); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "getEncodedPem fail."); + return ""; + } + string str = string(encoded); + HcfFree(encoded); + return str; +} +} // namespace + namespace ANI::CryptoFramework { PriKeyImpl::PriKeyImpl() {} @@ -33,7 +54,11 @@ int64_t PriKeyImpl::GetPriKeyObj() void PriKeyImpl::ClearMem() { - TH_THROW(std::runtime_error, "ClearMem not implemented"); + if (this->priKey_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "priKey obj is nullptr!"); + return; + } + this->priKey_->clearMem(this->priKey_); } OptKeySpec PriKeyImpl::GetAsyKeySpec(AsyKeySpecEnum itemType) @@ -43,12 +68,33 @@ OptKeySpec PriKeyImpl::GetAsyKeySpec(AsyKeySpecEnum itemType) DataBlob PriKeyImpl::GetEncodedDer(string_view format) { - TH_THROW(std::runtime_error, "GetEncodedDer not implemented"); + if (this->priKey_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "priKey obj is nullptr!"); + return {}; + } + HcfBlob outBlob = {}; + HcfResult res = this->priKey_->getEncodedDer(this->priKey_, format.c_str(), &outBlob); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "getEncodedDer fail."); + return {}; + } + array data = {}; + DataBlobToArrayU8(outBlob, data); + HcfBlobDataClearAndFree(&outBlob); + return { data }; +} + +string PriKeyImpl::GetEncodedPem(string_view format) +{ + return GetEncodedPemInner(this->priKey_, nullptr, format); } -string PriKeyImpl::GetEncodedPem(string_view format, optional_view config) +string PriKeyImpl::GetEncodedPemEx(string_view format, KeyEncodingConfig const& config) { - TH_THROW(std::runtime_error, "GetEncodedPem not implemented"); + HcfKeyEncodingParamsSpec spec = {}; + spec.password = const_cast(config.password.c_str()); + spec.cipher = const_cast(config.cipherName.c_str()); + return GetEncodedPemInner(this->priKey_, reinterpret_cast(&spec), format); } int64_t PriKeyImpl::GetKeyObj() @@ -68,7 +114,8 @@ DataBlob PriKeyImpl::GetEncoded() ANI_LOGE_THROW(res, "getEncoded failed."); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_pub_key.cpp b/frameworks/js/ani/src/ani_pub_key.cpp index 1762147f2cb11d9214b20aa08e5db506d63f63a4..c000e5fb21d3e6d2a3e4c451c7aadb4cbb21a573 100644 --- a/frameworks/js/ani/src/ani_pub_key.cpp +++ b/frameworks/js/ani/src/ani_pub_key.cpp @@ -38,12 +38,37 @@ OptKeySpec PubKeyImpl::GetAsyKeySpec(AsyKeySpecEnum itemType) DataBlob PubKeyImpl::GetEncodedDer(string_view format) { - TH_THROW(std::runtime_error, "GetEncodedDer not implemented"); + if (this->pubKey_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "pubKey obj is nullptr!"); + return {}; + } + HcfBlob outBlob = {}; + HcfResult res = this->pubKey_->getEncodedDer(this->pubKey_, format.c_str(), &outBlob); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "getEncodedDer failed."); + return {}; + } + array data = {}; + DataBlobToArrayU8(outBlob, data); + HcfBlobDataClearAndFree(&outBlob); + return { data }; } string PubKeyImpl::GetEncodedPem(string_view format) { - TH_THROW(std::runtime_error, "GetEncodedPem not implemented"); + if (this->pubKey_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "pubKey obj is nullptr!"); + return ""; + } + char *encoded = nullptr; + HcfResult res = this->pubKey_->base.getEncodedPem(&this->pubKey_->base, format.c_str(), &encoded); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "getEncodedPem failed."); + return ""; + } + string str = string(encoded); + HcfFree(encoded); + return str; } int64_t PubKeyImpl::GetKeyObj() @@ -63,7 +88,8 @@ DataBlob PubKeyImpl::GetEncoded() ANI_LOGE_THROW(res, "getEncoded failed."); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_rand.cpp b/frameworks/js/ani/src/ani_rand.cpp index a8dfb23731e87415502aae872ae1816083dd52bd..788de50d15aca8182d691aaed4af8461a285966f 100644 --- a/frameworks/js/ani/src/ani_rand.cpp +++ b/frameworks/js/ani/src/ani_rand.cpp @@ -38,7 +38,8 @@ DataBlob RandomImpl::GenerateRandomSync(int32_t len) ANI_LOGE_THROW(res, "generateRandom failed!"); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_sign.cpp b/frameworks/js/ani/src/ani_sign.cpp index 379ada0d274163dcd1b28efb23d7ec5cb1809b1c..659ee14367fc5f2b0060b5dfc01e804dfdd2b686 100644 --- a/frameworks/js/ani/src/ani_sign.cpp +++ b/frameworks/js/ani/src/ani_sign.cpp @@ -32,8 +32,8 @@ void SignImpl::InitSync(weak::PriKey priKey) ANI_LOGE_THROW(HCF_INVALID_PARAMS, "sign obj is nullptr!"); return; } - HcfPriKey *obj = reinterpret_cast(priKey->GetPriKeyObj()); - HcfResult res = this->sign_->init(this->sign_, nullptr, obj); + HcfPriKey *hcfPriKey = reinterpret_cast(priKey->GetPriKeyObj()); + HcfResult res = this->sign_->init(this->sign_, nullptr, hcfPriKey); if (res != HCF_SUCCESS) { ANI_LOGE_THROW(res, "sign init failed."); return; @@ -73,7 +73,8 @@ DataBlob SignImpl::SignSync(OptDataBlob const& data) ANI_LOGE_THROW(res, "sign doFinal failed!"); return {}; } - array out(move_data_t{}, outBlob.data, outBlob.len); + array out = {}; + DataBlobToArrayU8(outBlob, out); HcfBlobDataClearAndFree(&outBlob); return { out }; } diff --git a/frameworks/js/ani/src/ani_sm2_crypto_util.cpp b/frameworks/js/ani/src/ani_sm2_crypto_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33c21db3394e10dd9c889c44a2544fe74ceff1f8 --- /dev/null +++ b/frameworks/js/ani/src/ani_sm2_crypto_util.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_sm2_crypto_util.h" +#include "sm2_crypto_params.h" +#include "sm2_crypto_util.h" + +namespace ANI::CryptoFramework { +DataBlob GenCipherTextBySpec(SM2CipherTextSpec const& spec, optional_view mode) +{ + Sm2CipherTextSpec hcfSpec = {}; + ArrayU8ToDataBlob(spec.xCoordinate, hcfSpec.xCoordinate); + ArrayU8ToDataBlob(spec.yCoordinate, hcfSpec.yCoordinate); + ArrayU8ToDataBlob(spec.cipherTextData, hcfSpec.cipherTextData); + ArrayU8ToDataBlob(spec.hashData, hcfSpec.hashData); + string dataMode = mode.has_value() ? mode.value() : ""; + HcfBlob outBlob = {}; + HcfResult res = HcfGenCipherTextBySpec(&hcfSpec, dataMode.c_str(), &outBlob); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "gen cipher text by spec fail."); + return {}; + } + array data = {}; + DataBlobToArrayU8(outBlob, data); + HcfBlobDataClearAndFree(&outBlob); + return { data }; +} + +SM2CipherTextSpec GetCipherTextSpec(DataBlob const& cipherText, optional_view mode) +{ + HcfBlob inBlob = {}; + ArrayU8ToDataBlob(cipherText.data, inBlob); + string dataMode = mode.has_value() ? mode.value() : ""; + Sm2CipherTextSpec *hcfSpec = nullptr; + HcfResult res = HcfGetCipherTextSpec(&inBlob, dataMode.c_str(), &hcfSpec); + if (res != HCF_SUCCESS) { + ANI_LOGE_THROW(res, "get cipher text spec fail."); + return {}; + } + SM2CipherTextSpec spec = {}; + DataBlobToArrayU8(hcfSpec->xCoordinate, spec.xCoordinate); + DataBlobToArrayU8(hcfSpec->yCoordinate, spec.yCoordinate); + DataBlobToArrayU8(hcfSpec->cipherTextData, spec.cipherTextData); + DataBlobToArrayU8(hcfSpec->hashData, spec.hashData); + DestroySm2CipherTextSpec(hcfSpec); + return spec; +} +} // namespace ANI::CryptoFramework + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_GenCipherTextBySpec(ANI::CryptoFramework::GenCipherTextBySpec); +TH_EXPORT_CPP_API_GetCipherTextSpec(ANI::CryptoFramework::GetCipherTextSpec); +// NOLINTEND diff --git a/frameworks/js/ani/src/ani_sym_key.cpp b/frameworks/js/ani/src/ani_sym_key.cpp index 23323c7eb6257d8a8bd10ac75df5e91f7cfc0eee..3cfe429cbb360c3ef29ac023cc2ae188b31be9c7 100644 --- a/frameworks/js/ani/src/ani_sym_key.cpp +++ b/frameworks/js/ani/src/ani_sym_key.cpp @@ -38,7 +38,11 @@ int64_t SymKeyImpl::GetSymKeyObj() void SymKeyImpl::ClearMem() { - TH_THROW(std::runtime_error, "ClearMem not implemented"); + if (this->symKey_ == nullptr) { + ANI_LOGE_THROW(HCF_INVALID_PARAMS, "symKey obj is nullptr!"); + return; + } + this->symKey_->clearMem(this->symKey_); } DataBlob SymKeyImpl::GetEncoded() @@ -53,7 +57,8 @@ DataBlob SymKeyImpl::GetEncoded() ANI_LOGE_THROW(res, "getEncoded failed."); return {}; } - array data(move_data_t{}, outBlob.data, outBlob.len); + array data = {}; + DataBlobToArrayU8(outBlob, data); HcfBlobDataClearAndFree(&outBlob); return { data }; } diff --git a/frameworks/js/ani/src/ani_verify.cpp b/frameworks/js/ani/src/ani_verify.cpp index f1f48cff83890e2f619c1367977f8ebac5975850..0504abbc9072722254ba0beb77efe8c7c3d769c8 100644 --- a/frameworks/js/ani/src/ani_verify.cpp +++ b/frameworks/js/ani/src/ani_verify.cpp @@ -19,7 +19,7 @@ namespace ANI::CryptoFramework { VerifyImpl::VerifyImpl() {} -VerifyImpl::VerifyImpl(HcfVerify *obj) : verify_(obj) {} +VerifyImpl::VerifyImpl(HcfVerify *verify) : verify_(verify) {} VerifyImpl::~VerifyImpl() { @@ -33,8 +33,8 @@ void VerifyImpl::InitSync(weak::PubKey pubKey) ANI_LOGE_THROW(HCF_INVALID_PARAMS, "verify obj is nullptr!"); return; } - HcfPubKey *obj = reinterpret_cast(pubKey->GetPubKeyObj()); - HcfResult res = this->verify_->init(this->verify_, nullptr, obj); + HcfPubKey *hcfPubKey = reinterpret_cast(pubKey->GetPubKeyObj()); + HcfResult res = this->verify_->init(this->verify_, nullptr, hcfPubKey); if (res != HCF_SUCCESS) { ANI_LOGE_THROW(res, "verify init failed."); return; diff --git a/frameworks/js/ani/src/impl/ohos.security.cryptoFramework.cryptoFramework.impl.cpp b/frameworks/js/ani/src/impl/ohos.security.cryptoFramework.cryptoFramework.impl.cpp index eb429d2edde46539638ecda6c0376e1186f3a058..c13a9853bcc6c10f29d4117c8f4a9842a71db5f7 100644 --- a/frameworks/js/ani/src/impl/ohos.security.cryptoFramework.cryptoFramework.impl.cpp +++ b/frameworks/js/ani/src/impl/ohos.security.cryptoFramework.cryptoFramework.impl.cpp @@ -138,10 +138,14 @@ public: TH_THROW(std::runtime_error, "GetEncodedDer not implemented"); } - string GetEncodedPem(string_view format, optional_view config) { + string GetEncodedPem(string_view format) { TH_THROW(std::runtime_error, "GetEncodedPem not implemented"); } + string GetEncodedPemEx(string_view format, KeyEncodingConfig const& config) { + TH_THROW(std::runtime_error, "GetEncodedPemEx not implemented"); + } + int64_t GetKeyObj() { TH_THROW(std::runtime_error, "GetKeyObj not implemented"); } @@ -289,7 +293,13 @@ public: return make_holder(); } - KeyPair ConvertPemKeySync(OptString const& pubKey, OptString const& priKey, optional_view password) { + KeyPair ConvertPemKeySync(OptString const& pubKey, OptString const& priKey) { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return make_holder(); + } + + KeyPair ConvertPemKeySyncEx(OptString const& pubKey, OptString const& priKey, string_view password) { // The parameters in the make_holder function should be of the same type // as the parameters in the constructor of the actual implementation class. return make_holder(); @@ -333,6 +343,14 @@ public: TH_THROW(std::runtime_error, "DoFinalSync not implemented"); } + void SetCipherSpec(CipherSpecEnum itemType, array_view itemValue) { + TH_THROW(std::runtime_error, "SetCipherSpec not implemented"); + } + + OptStrUint8Arr GetCipherSpec(CipherSpecEnum itemType) { + TH_THROW(std::runtime_error, "GetCipherSpec not implemented"); + } + string GetAlgName() { TH_THROW(std::runtime_error, "GetAlgName not implemented"); } @@ -433,6 +451,42 @@ public: } }; +class KeyAgreementImpl { +public: + KeyAgreementImpl() { + // Don't forget to implement the constructor. + } + + DataBlob GenerateSecretSync(weak::PriKey priKey, weak::PubKey pubKey) { + TH_THROW(std::runtime_error, "GenerateSecretSync not implemented"); + } + + string GetAlgName() { + TH_THROW(std::runtime_error, "GetAlgName not implemented"); + } +}; + +class DHKeyUtilImpl { +public: + DHKeyUtilImpl() { + // Don't forget to implement the constructor. + } +}; + +class ECCKeyUtilImpl { +public: + ECCKeyUtilImpl() { + // Don't forget to implement the constructor. + } +}; + +class SM2CryptoUtilImpl { +public: + SM2CryptoUtilImpl() { + // Don't forget to implement the constructor. + } +}; + Md CreateMd(string_view algName) { // The parameters in the make_holder function should be of the same type // as the parameters in the constructor of the actual implementation class. @@ -451,6 +505,12 @@ Mac CreateMac(string_view algName) { return make_holder(); } +Mac CreateMacBySpec(OptExtMacSpec const& macSpec) { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return make_holder(); +} + SymKeyGenerator CreateSymKeyGenerator(string_view algName) { // The parameters in the make_holder function should be of the same type // as the parameters in the constructor of the actual implementation class. @@ -492,6 +552,36 @@ AsyKeyGeneratorBySpec CreateAsyKeyGeneratorBySpec(OptAsyKeySpec const& asyKeySpe // as the parameters in the constructor of the actual implementation class. return make_holder(); } + +KeyAgreement CreateKeyAgreement(string_view algName) { + // The parameters in the make_holder function should be of the same type + // as the parameters in the constructor of the actual implementation class. + return make_holder(); +} + +DHCommonParamsSpec GenDHCommonParamsSpec(int32_t pLen, optional_view skLen) { + TH_THROW(std::runtime_error, "GenDHCommonParamsSpec not implemented"); +} + +ECCCommonParamsSpec GenECCCommonParamsSpec(string_view curveName) { + TH_THROW(std::runtime_error, "GenECCCommonParamsSpec not implemented"); +} + +Point ConvertPoint(string_view curveName, array_view encodedPoint) { + TH_THROW(std::runtime_error, "ConvertPoint not implemented"); +} + +array GetEncodedPoint(string_view curveName, Point const& point, string_view format) { + TH_THROW(std::runtime_error, "GetEncodedPoint not implemented"); +} + +DataBlob GenCipherTextBySpec(SM2CipherTextSpec const& spec, optional_view mode) { + TH_THROW(std::runtime_error, "GenCipherTextBySpec not implemented"); +} + +SM2CipherTextSpec GetCipherTextSpec(DataBlob const& cipherText, optional_view mode) { + TH_THROW(std::runtime_error, "GetCipherTextSpec not implemented"); +} } // namespace // Since these macros are auto-generate, lint will cause false positive. @@ -499,6 +589,7 @@ AsyKeyGeneratorBySpec CreateAsyKeyGeneratorBySpec(OptAsyKeySpec const& asyKeySpe TH_EXPORT_CPP_API_CreateMd(CreateMd); TH_EXPORT_CPP_API_CreateRandom(CreateRandom); TH_EXPORT_CPP_API_CreateMac(CreateMac); +TH_EXPORT_CPP_API_CreateMacBySpec(CreateMacBySpec); TH_EXPORT_CPP_API_CreateSymKeyGenerator(CreateSymKeyGenerator); TH_EXPORT_CPP_API_CreateAsyKeyGenerator(CreateAsyKeyGenerator); TH_EXPORT_CPP_API_CreateKdf(CreateKdf); @@ -506,4 +597,11 @@ TH_EXPORT_CPP_API_CreateCipher(CreateCipher); TH_EXPORT_CPP_API_CreateVerify(CreateVerify); TH_EXPORT_CPP_API_CreateSign(CreateSign); TH_EXPORT_CPP_API_CreateAsyKeyGeneratorBySpec(CreateAsyKeyGeneratorBySpec); +TH_EXPORT_CPP_API_CreateKeyAgreement(CreateKeyAgreement); +TH_EXPORT_CPP_API_GenDHCommonParamsSpec(GenDHCommonParamsSpec); +TH_EXPORT_CPP_API_GenECCCommonParamsSpec(GenECCCommonParamsSpec); +TH_EXPORT_CPP_API_ConvertPoint(ConvertPoint); +TH_EXPORT_CPP_API_GetEncodedPoint(GetEncodedPoint); +TH_EXPORT_CPP_API_GenCipherTextBySpec(GenCipherTextBySpec); +TH_EXPORT_CPP_API_GetCipherTextSpec(GetCipherTextSpec); // NOLINTEND diff --git a/frameworks/js/ani/test/arktsconfig.json b/frameworks/js/ani/test/arktsconfig.json index 697340388f74caafb268c583bd4d2e5ad0947dad..53466af36da1a802f1958527ded7d4f62f475ad5 100644 --- a/frameworks/js/ani/test/arktsconfig.json +++ b/frameworks/js/ani/test/arktsconfig.json @@ -17,5 +17,10 @@ }, "includes": [ "*.ets" + ], + "#files": [ + "./test_utils.ets", + "./test_main.ets", + "./test_rand.ets" ] } diff --git a/frameworks/js/ani/test/test_asy_key_generator.ets b/frameworks/js/ani/test/test_asy_key_generator.ets index f3836b50776e94b21f49f6bd75ef5cb62834111b..9d446e3fff93bbe819430b2bec41c00159dab376 100644 --- a/frameworks/js/ani/test/test_asy_key_generator.ets +++ b/frameworks/js/ani/test/test_asy_key_generator.ets @@ -21,12 +21,16 @@ function testAsyKeyGeneratorSync() { try { let generator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2'); let keyPair = generator.generateKeyPairSync(); - let pkBlob = keyPair.pubKey.getEncoded(); - let skBlob = keyPair.priKey.getEncoded(); + let pubKey = keyPair.pubKey; + let priKey = keyPair.priKey; + let pkBlob = pubKey.getEncoded(); + let skBlob = priKey.getEncoded(); let pkStr = utils.uint8ArrayToHexStr(pkBlob.data); let skStr = utils.uint8ArrayToHexStr(skBlob.data); + console.log("AsyKeyGenerator algName: " + generator.algName); console.info('generateKeyPair pubKey: ' + pkStr); console.info('generateKeyPair priKey: ' + skStr); + priKey.clearMem(); } catch (err: BusinessError) { console.error(`[error] generateKeyPair: ${err.code} ${err.message}`); } @@ -56,13 +60,55 @@ function testAsyKeyConvertKeySync() { }; let generator = cryptoFramework.createAsyKeyGenerator('SM2_256'); let keyPair = generator.convertKeySync(pubKeyBlob, priKeyBlob); - let pkBlob = keyPair.pubKey.getEncoded(); - let skBlob = keyPair.priKey.getEncoded(); + let pubKey = keyPair.pubKey; + let priKey = keyPair.priKey; + let pkBlob = pubKey.getEncoded(); + let skBlob = priKey.getEncoded(); let pkStr = utils.uint8ArrayToHexStr(pkBlob.data); let skStr = utils.uint8ArrayToHexStr(skBlob.data); console.log("AsyKeyGenerator algName: " + generator.algName); + console.info('convertKey pubKey: ' + pkStr); + console.info('convertKey priKey: ' + skStr); + priKey.clearMem(); + } catch (err: BusinessError) { + console.error(`[error] convertKey: ${err.code} ${err.message}`); + } +} + +function testConvertPemKeySync() { + try { + let priKeyPkcs1Str1024: string = + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIICXQIBAAKBgQCwIN3mr21+N96ToxnVnaS+xyK9cNRAHiHGgrbjHw6RAj3V+l+W\n" + + "Y68IhIe3DudVlzE9oMjeOQwkMkq//HCxNlIlFR6O6pa0mrXSwPRE7YKG97CeKk2g\n" + + "YOS8YEh8toAvm7xKbiLkXuuMlxrjP2j/mb5iI/UASFSPZiQ/IyxDr0AQaQIDAQAB\n" + + "AoGAEvBFzBNa+7J4PXnRQlYEK/tvsd0bBZX33ceacMubHl6WVZbphltLq+fMTBPP\n" + + "LjXmtpC+aJ7Lvmyl+wTi/TsxE9vxW5JnbuRT48rnZ/Xwq0eozDeEeIBRrpsr7Rvr\n" + + "7ctrgzr4m4yMHq9aDgpxj8IR7oHkfwnmWr0wM3FuiVlj650CQQDineeNZ1hUTkj4\n" + + "D3O+iCi3mxEVEeJrpqrmSFolRMb+iozrIRKuJlgcOs+Gqi2fHfOTTL7LkpYe8SVg\n" + + "e3JxUdVLAkEAxvcZXk+byMFoetrnlcMR13VHUpoVeoV9qkv6CAWLlbMdgf7uKmgp\n" + + "a1Yp3QPDNQQqkPvrqtfR19JWZ4uy1qREmwJALTU3BjyBoH/liqb6fh4HkWk75Som\n" + + "MzeSjFIOubSYxhq5tgZpBZjcpvUMhV7Zrw54kwASZ+YcUJvmyvKViAm9NQJBAKF7\n" + + "DyXSKrem8Ws0m1ybM7HQx5As6l3EVhePDmDQT1eyRbKp+xaD74nkJpnwYdB3jyyY\n" + + "qc7A1tj5J5NmeEFolR0CQQCn76Xp8HCjGgLHw9vg7YyIL28y/XyfFyaZAzzK+Yia\n" + + "akNwQ6NeGtXSsuGCcyyfpacHp9xy8qXQNKSkw03/5vDO\n" + + "-----END RSA PRIVATE KEY-----\n"; + let publicPkcs1Str1024: string = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIGJAoGBALAg3eavbX433pOjGdWdpL7HIr1w1EAeIcaCtuMfDpECPdX6X5ZjrwiE\n" + + "h7cO51WXMT2gyN45DCQySr/8cLE2UiUVHo7qlrSatdLA9ETtgob3sJ4qTaBg5Lxg\n" + + "SHy2gC+bvEpuIuRe64yXGuM/aP+ZvmIj9QBIVI9mJD8jLEOvQBBpAgMBAAE=\n" + + "-----END RSA PUBLIC KEY-----\n"; + let generator = cryptoFramework.createAsyKeyGenerator('RSA1024'); + let keyPair = generator.convertPemKeySync(publicPkcs1Str1024, priKeyPkcs1Str1024); + let pubKey = keyPair.pubKey; + let priKey = keyPair.priKey; + let pkStr = pubKey.getEncodedPem('X509'); + let skStr = priKey.getEncodedPem('PKCS8'); + console.log("AsyKeyGenerator algName: " + generator.algName); console.info('convertPemKey pubKey: ' + pkStr); console.info('convertPemKey priKey: ' + skStr); + priKey.clearMem(); } catch (err: BusinessError) { console.error(`[error] convertPemKey: ${err.code} ${err.message}`); } @@ -73,4 +119,6 @@ export function testAsyKeyGenerator() { testAsyKeyGeneratorSync(); console.log(">>>>>>>>>>>>>>>>>>>> AsyKeyConvertKeySync"); testAsyKeyConvertKeySync(); + console.log(">>>>>>>>>>>>>>>>>>>> AsyKeyConvertPemKeySync"); + testConvertPemKeySync(); } diff --git a/frameworks/js/ani/test/test_dh_key_util.ets b/frameworks/js/ani/test/test_dh_key_util.ets new file mode 100644 index 0000000000000000000000000000000000000000..43026d120ff4d5411d2a7e5ff8cc50b6607f5a7e --- /dev/null +++ b/frameworks/js/ani/test/test_dh_key_util.ets @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError } from "@ohos.base"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import utils from "./test_utils"; + +function testGenDHCommonParamsSpec() { + try { + let spec = cryptoFramework.DHKeyUtil.genDHCommonParamsSpec(2048, 1024); + console.log("DHKeyUtil.genDHCommonParamsSpec:"); + console.log("DHCommonParamsSpec spec.algName: " + spec.algName); + console.log("DHCommonParamsSpec spec.specType: " + spec.specType); + console.log("DHCommonParamsSpec spec.p: " + spec.p); + console.log("DHCommonParamsSpec spec.g: " + spec.g); + console.log("DHCommonParamsSpec spec.l: " + spec.l); + } catch (err: BusinessError) { + console.error(`[error] DHKeyUtil.genDHCommonParamsSpec: ${err.code} ${err.message}`); + } +} + +export function testDHKeyUtil() { + console.log(">>>>>>>>>>>>>>>>>>>> GenDHCommonParamsSpec"); + testGenDHCommonParamsSpec(); +} diff --git a/frameworks/js/ani/test/test_ecc_key_util.ets b/frameworks/js/ani/test/test_ecc_key_util.ets new file mode 100644 index 0000000000000000000000000000000000000000..061423a6d37f9f9c578bb6a961f74a682efa9b13 --- /dev/null +++ b/frameworks/js/ani/test/test_ecc_key_util.ets @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError } from "@ohos.base"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import utils from "./test_utils"; + +function testGenECCCommonParamsSpec() { + try { + let spec = cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_brainpoolP256r1'); + let ecFiledFp = spec.field as cryptoFramework.ECFieldFp; + console.log("ECCKeyUtil.genECCCommonParamsSpec:"); + console.log("ECCCommonParamsSpec spec.algName: " + spec.algName); + console.log("ECCCommonParamsSpec spec.specType: " + spec.specType); + console.log("ECCCommonParamsSpec spec.field.fieldType: " + ecFiledFp.fieldType); + console.log("ECCCommonParamsSpec spec.field.p: " + ecFiledFp.p); + console.log("ECCCommonParamsSpec spec.a: " + spec.a); + console.log("ECCCommonParamsSpec spec.b: " + spec.b); + console.log("ECCCommonParamsSpec spec.g.x: " + spec.g.x); + console.log("ECCCommonParamsSpec spec.g.y: " + spec.g.y); + console.log("ECCCommonParamsSpec spec.n: " + spec.n); + console.log("ECCCommonParamsSpec spec.h: " + spec.h); + } catch (err: BusinessError) { + console.error(`[error] ECCKeyUtil.genECCCommonParamsSpec: ${err.code} ${err.message}`); + } +} + +function testConvertPoint() { + try { + let pkData = new Uint8Array([ + 0x04, 0x8F, 0x27, 0x39, 0xF9, 0x91, 0x32, 0x3F, 0xDE, 0x23, 0x46, 0xB2, 0x79, 0xCA, 0x9A, 0x15, + 0x92, 0x81, 0x4B, 0x4C, 0x3F, 0x08, 0xC3, 0x9D, 0x6F, 0x28, 0xD9, 0xD7, 0x94, 0x78, 0xE0, 0xCD, + 0x52, 0x53, 0x5C, 0xB9, 0x15, 0xD3, 0xB8, 0x05, 0x13, 0x72, 0x21, 0x56, 0x55, 0xE4, 0x7B, 0xF2, + 0xCE, 0xC8, 0x62, 0xB2, 0xB8, 0x82, 0x23, 0xE8, 0x2D, 0x05, 0xCA, 0xBD, 0x0B, 0x2E, 0xA3, 0x9C, + 0x98 + ]); + let point = cryptoFramework.ECCKeyUtil.convertPoint('NID_brainpoolP256r1', pkData); + console.log("ECCKeyUtil.convertPoint:"); + console.log("Point point.x: " + point.x); + console.log("Point point.y: " + point.y); + } catch (err: BusinessError) { + console.error(`[error] ECCKeyUtil.convertPoint: ${err.code} ${err.message}`); + } +} + +function testGetEncodedPoint() { + try { + let point: cryptoFramework.Point = { + x: BigInt('64750044510792891439269945828433327517677381559622384455951527515863444933970'), + y: BigInt('37705793773900352766227640862738381713868374157045352837992005507978837073048') + }; + let encoded = cryptoFramework.ECCKeyUtil.getEncodedPoint('NID_brainpoolP256r1', point, 'COMPRESSED'); + console.log("ECCKeyUtil.getEncodedPoint:"); + console.log("Uint8Array encoded: " + encoded); + } catch (err: BusinessError) { + console.error(`[error] ECCKeyUtil.getEncodedPoint: ${err.code} ${err.message}`); + } +} + +export function testECCKeyUtil() { + console.log(">>>>>>>>>>>>>>>>>>>> GenECCCommonParamsSpec"); + testGenECCCommonParamsSpec(); + console.log(">>>>>>>>>>>>>>>>>>>> ConvertPoint"); + testConvertPoint(); + console.log(">>>>>>>>>>>>>>>>>>>> GetEncodedPoint"); + testGetEncodedPoint(); +} diff --git a/frameworks/js/ani/test/test_key_agreement.ets b/frameworks/js/ani/test/test_key_agreement.ets new file mode 100644 index 0000000000000000000000000000000000000000..20fa962e19196a94bc7024243dc531459c465d65 --- /dev/null +++ b/frameworks/js/ani/test/test_key_agreement.ets @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError } from "@ohos.base"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import utils from "./test_utils"; + +function testKeyAgreementSync() +{ + try { + let pubKeyArray = new Uint8Array([ + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x53, 0x60, 0x8E, 0x09, 0x56, + 0xD6, 0x7E, 0x6A, 0xF7, 0xE9, 0x5C, 0x7D, 0x04, 0x80, 0x8A, 0x69, 0xF6, 0xA2, 0xD7, 0x47, 0x51, + 0x3A, 0xCA, 0x79, 0x1A, 0x69, 0xD3, 0x37, 0x82, 0x2D, 0xEC, 0x8F, 0x37, 0x10, 0xF8, 0x4B, 0xA7, + 0xA0, 0xA7, 0x6A, 0x02, 0x98, 0xF3, 0x2C, 0x44, 0x42, 0x00, 0xA7, 0x63, 0x5C, 0xEB, 0xD7, 0x9F, + 0xEF, 0x1C, 0x6A, 0x7C, 0xAB, 0x22, 0x91, 0x7C, 0xAE, 0x39, 0x5C + ]); + let priKeyArray = new Uint8Array([ + 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0x73, 0x38, 0x89, 0x23, 0xCF, 0x00, 0x3C, 0xBF, 0x5A, + 0x3D, 0x88, 0x69, 0xD2, 0x10, 0x1B, 0x04, 0xAB, 0x39, 0x0A, 0x3D, 0x7B, 0x28, 0xBD, 0x1C, 0x22, + 0xCF, 0xEC, 0x16, 0x2D, 0xDF, 0x0A, 0xBD, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07 + ]); + let generator = cryptoFramework.createAsyKeyGenerator('ECC256'); + let keyPairA = generator.convertKeySync({ data: pubKeyArray }, { data: priKeyArray }); + let keyPairB = generator.generateKeyPairSync(); + let keyAgreement = cryptoFramework.createKeyAgreement('ECC256'); + console.log("KeyAgreement algName: " + keyAgreement.algName); + let secret1 = keyAgreement.generateSecretSync(keyPairA.priKey, keyPairB.pubKey); + let secret2 = keyAgreement.generateSecretSync(keyPairB.priKey, keyPairA.pubKey); + if (secret1.data.toString() === secret2.data.toString()) { + console.info('KeyAgreement ecdh result is equal'); + console.info('KeyAgreement ecdh secret.data: ' + utils.uint8ArrayToHexStr(secret1.data)); + } else { + console.error('KeyAgreement ecdh result is not equal'); + } + } catch (err: BusinessError) { + console.error(`[error] KeyAgreement: ${err.code} ${err.message}`); + } +} + +export function testKeyAgreement() +{ + console.log(">>>>>>>>>>>>>>>>>>>> KeyAgreementSync"); + testKeyAgreementSync(); +} diff --git a/frameworks/js/ani/test/test_mac.ets b/frameworks/js/ani/test/test_mac.ets index 99006c4d3932d70ea5b2968c3968af42e3f741aa..c042492c5eb951f238dfa54235348493219ade0c 100644 --- a/frameworks/js/ani/test/test_mac.ets +++ b/frameworks/js/ani/test/test_mac.ets @@ -19,26 +19,30 @@ import utils from "./test_utils"; function testMacSync() { try { - let key = "1234567890"; + let key = "12345678abcdefgh"; let data = "Hello World"; - let keyBytes = utils.hexStrToUint8Array(key); + let keyBytes = utils.stringToUint8Array(key); let dataBytes = utils.stringToUint8Array(data); - let generator = cryptoFramework.createSymKeyGenerator("HMAC"); + let generator = cryptoFramework.createSymKeyGenerator("AES128"); let symKey = generator.convertKeySync({ data: keyBytes }); - let mac = cryptoFramework.createMac("SHA256"); + let spec: cryptoFramework.CmacSpec = { + algName: "CMAC", + cipherName: "AES128", + }; + let mac = cryptoFramework.createMac(spec); mac.initSync(symKey); mac.updateSync({ data: dataBytes }); let output = mac.doFinalSync(); let str = utils.uint8ArrayToHexStr(output.data); - console.log("HMAC algName: " + mac.algName); - console.log("HMAC-SHA256: " + str); + console.log("CMAC algName: " + mac.algName); + console.log("CMAC-AES128: " + str); } catch (err: BusinessError) { - console.error(`[error] HMAC-SHA256: ${err.code} ${err.message}`); + console.error(`[error] CMAC-AES128: ${err.code} ${err.message}`); } } diff --git a/frameworks/js/ani/test/test_main.ets b/frameworks/js/ani/test/test_main.ets index b63facabde66aaa18fea73a239441cec596804ed..1ed3e686c9acb0218261a81fe5fc167e043ff7f1 100644 --- a/frameworks/js/ani/test/test_main.ets +++ b/frameworks/js/ani/test/test_main.ets @@ -23,6 +23,10 @@ import { testAsyKeyGeneratorBySpec } from "./test_asy_key_generator_by_spec"; import { testCipher } from "./test_cipher"; import { testSign } from "./test_sign"; import { testVerify } from "./test_verify"; +import { testKeyAgreement } from "./test_key_agreement"; +import { testDHKeyUtil } from "./test_dh_key_util"; +import { testECCKeyUtil } from "./test_ecc_key_util"; +import { testSM2CryptoUtil } from "./test_sm2_crypto_util"; function main() { testRandom(); @@ -35,4 +39,8 @@ function main() { testCipher(); testSign(); testVerify(); + testKeyAgreement(); + testDHKeyUtil(); + testECCKeyUtil(); + testSM2CryptoUtil(); } diff --git a/frameworks/js/ani/test/test_rand.ets b/frameworks/js/ani/test/test_rand.ets index c4fe3ac244d2edaea168f594e5ce44779c19c970..94d72fa895cfefb9551edc40cbde3f38b0a38631 100644 --- a/frameworks/js/ani/test/test_rand.ets +++ b/frameworks/js/ani/test/test_rand.ets @@ -35,7 +35,52 @@ function testRandomSync() { } } +function testRandomAsync() { + try { + let data = "Hello World"; + let dataBytes = utils.stringToUint8Array(data); + let random = cryptoFramework.createRandom(); + random.setSeed({ + data: dataBytes + }); + let output = await random.generateRandom(16); + let str = utils.uint8ArrayToHexStr(output.data); + console.log("Random algName: " + random.algName); + console.log("Random: " + str); + } catch (err: BusinessError) { + console.error(`[error] Random: ${err.code} ${err.message}`); + } +} + +function testRandomCallback() { + try { + let data = "Hello World"; + let dataBytes = utils.stringToUint8Array(data); + let random = cryptoFramework.createRandom(); + random.setSeed({ + data: dataBytes + }); + random.generateRandom(16, (err, dataBlob) => { + console.log(`Random: ${err}`); + console.log(`Random: ${err.code} ${err.message}`); + if (err) { + console.error(`[error] Random: ${err.code} ${err.message}`); + } else { + let str = utils.uint8ArrayToHexStr(dataBlob.data); + console.log("Random algName: " + random.algName); + console.log("Random: " + str); + } + }); + } catch (err: BusinessError) { + console.error(`[error] Random: ${err.code} ${err.message}`); + } +} + export function testRandom() { console.log(">>>>>>>>>>>>>>>>>>>> RandomSync"); testRandomSync(); + console.log(">>>>>>>>>>>>>>>>>>>> RandomAsync"); + testRandomAsync(); + console.log(">>>>>>>>>>>>>>>>>>>> RandomCallback"); + testRandomCallback(); } diff --git a/frameworks/js/ani/test/test_sm2_crypto_util.ets b/frameworks/js/ani/test/test_sm2_crypto_util.ets new file mode 100644 index 0000000000000000000000000000000000000000..4e3b4e107f12983aeda5b4fdc34c5ee9bc627a04 --- /dev/null +++ b/frameworks/js/ani/test/test_sm2_crypto_util.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BusinessError } from "@ohos.base"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import utils from "./test_utils"; + +function testGenCipherTextBySpec() { + try { + let spec: cryptoFramework.SM2CipherTextSpec = { + xCoordinate: BigInt('20625015362595980457695435345498579729138244358573902431560627260141789922999'), + yCoordinate: BigInt('48563164792857017065725892921053777369510340820930241057309844352421738767712'), + cipherTextData: new Uint8Array([ + 0x64, 0xE3, 0x4E, 0xC3, 0xF9, 0xB3, 0x2B, 0x46, 0xF2, 0x45, 0xA9, 0x0A, 0x41, 0x7B + ]), + hashData: new Uint8Array([ + 0x57, 0xA7, 0xA7, 0xF7, 0x58, 0x92, 0xCB, 0xEA, 0x53, 0x7E, 0x75, 0x81, 0x34, 0x8E, 0x52, 0x36, + 0x98, 0xE2, 0xC9, 0x6F, 0x8F, 0x73, 0xA9, 0x7D, 0x80, 0x2A, 0x9D, 0x1F, 0x72, 0xC6, 0x6D, 0xF4 + ]) + } + let cipherText = cryptoFramework.SM2CryptoUtil.genCipherTextBySpec(spec, 'C1C3C2'); + console.log("SM2CryptoUtil.genCipherTextBySpec:"); + console.log("CipherText cipherText.data: " + cipherText.data); + } + catch (err: BusinessError) { + console.error(`[error] SM2CryptoUtil.genCipherTextBySpec: ${err.code} ${err.message}`); + } +} + +function testGetCipherTextSpec() { + try { + let cipherTextArray = new Uint8Array([ + 0x30, 0x76, 0x02, 0x20, 0x2D, 0x99, 0x58, 0x52, 0x68, 0xDD, 0xE2, 0x2B, 0xAE, 0x15, 0x7A, 0xF8, + 0x05, 0xE8, 0x69, 0x29, 0x5C, 0x5F, 0x66, 0xE0, 0xD8, 0x95, 0x55, 0xEC, 0x6E, 0x06, 0x40, 0xBC, + 0x95, 0x46, 0x46, 0xB7, 0x02, 0x20, 0x6B, 0x5D, 0xC6, 0xF7, 0x77, 0x12, 0x28, 0x6E, 0x5A, 0x9C, + 0xC1, 0x9E, 0xCD, 0x71, 0xAA, 0x80, 0x92, 0x6D, 0x4B, 0x11, 0xB5, 0x6D, 0x6E, 0x5B, 0x95, 0x05, + 0x6E, 0xE9, 0xD1, 0x4E, 0xE5, 0x60, 0x04, 0x20, 0x57, 0xA7, 0xA7, 0xF7, 0x58, 0x92, 0xCB, 0xEA, + 0x53, 0x7E, 0x75, 0x81, 0x34, 0x8E, 0x52, 0x36, 0x98, 0xE2, 0xC9, 0x6F, 0x8F, 0x73, 0xA9, 0x7D, + 0x80, 0x2A, 0x9D, 0x1F, 0x72, 0xC6, 0x6D, 0xF4, 0x04, 0x0E, 0x64, 0xE3, 0x4E, 0xC3, 0xF9, 0xB3, + 0x2B, 0x46, 0xF2, 0x45, 0xA9, 0x0A, 0x41, 0x7B + ]); + let cipherText: cryptoFramework.DataBlob = { + data: cipherTextArray + }; + let spec: cryptoFramework.SM2CipherTextSpec = cryptoFramework.SM2CryptoUtil.getCipherTextSpec(cipherText, 'C1C3C2'); + console.log("SM2CryptoUtil.getCipherTextSpec:"); + console.log("SM2CipherTextSpec spec.xCoordinate: " + spec.xCoordinate); + console.log("SM2CipherTextSpec spec.yCoordinate: " + spec.yCoordinate); + console.log("SM2CipherTextSpec spec.cipherTextData: " + utils.uint8ArrayToHexStr(spec.cipherTextData)); + console.log("SM2CipherTextSpec spec.hashData: " + utils.uint8ArrayToHexStr(spec.hashData)); + } + catch (err: BusinessError) { + console.error(`[error] SM2CryptoUtil.getCipherTextSpec: ${err.code} ${err.message}`); + } +} + +export function testSM2CryptoUtil() { + console.log(">>>>>>>>>>>>>>>>>>>> GenCipherTextBySpec"); + testGenCipherTextBySpec(); + console.log(">>>>>>>>>>>>>>>>>>>> GetCipherTextSpec"); + testGetCipherTextSpec(); +} diff --git a/frameworks/js/ani/test/test_sym_key_generator.ets b/frameworks/js/ani/test/test_sym_key_generator.ets index 56ebfc76279d822a112fdbff78d2d8de0df2d31d..88c10b8486e7c49bc8aad618fdde63254883413a 100644 --- a/frameworks/js/ani/test/test_sym_key_generator.ets +++ b/frameworks/js/ani/test/test_sym_key_generator.ets @@ -24,7 +24,10 @@ function testSymKeyGeneratorSync() { let encodedKey = symKey.getEncoded(); let str = utils.uint8ArrayToHexStr(encodedKey.data); console.log("SymKeyGenerator algName: " + generator.algName); + console.log("SymKeyGenerator symKey.algName: " + symKey.algName); + console.log("SymKeyGenerator symKey.format: " + symKey.format); console.log("generateSymKey: " + str); + symKey.clearMem(); } catch (err: BusinessError) { console.error(`[error] generateSymKey: ${err.code} ${err.message}`); } @@ -39,7 +42,11 @@ function testSymKeyConvertKeySync() { let symKey = generator.convertKeySync(keyBlob); let encodedKey = symKey.getEncoded(); let str = utils.uint8ArrayToHexStr(encodedKey.data); + console.log("SymKeyGenerator algName: " + generator.algName); + console.log("SymKeyGenerator symKey.algName: " + symKey.algName); + console.log("SymKeyGenerator symKey.format: " + symKey.format); console.log("convertKey: " + str); + symKey.clearMem(); } catch (err: BusinessError) { console.error(`[error] convertKey: ${err.code} ${err.message}`); }