import type { CryptoByteCipherOptions, CryptoCodecKind, CryptoDesOptions, CryptoDigestKind, CryptoMacKind, CryptoRsaPair, CryptoRuntimeSnapshot, CryptoTextCipherOptions, CryptoTripleDesOptions, RsaOutputKind } from '../interface.uts' import { buildRuntimeSnapshot, createDefaultByteCipherOptions, createDefaultDesOptions, createDefaultTextCipherOptions, createDefaultTripleDesOptions, normalizeByteCipherOptions, normalizeDesOptions, normalizeTextCipherOptions, normalizeTripleDesOptions, resolveHexOutput } from '../shared/options.uts' import type { CompatBridge, CompatCrypto } from '../shared/compat.uts' import { aesDecryptBytesCompat, aesDecryptCompat, aesEncryptBytesCompat, aesEncryptCompat, base64DecodeCompat, base64EncodeCompat, createCompatBridge, createCompatCrypto, desDecryptCompat, desEncryptCompat, generateRsaKeyPairCompat, hmacSha1Compat, hmacSha256Compat, hmacSha512Compat, md5Compat, rc4DecryptCompat, rc4EncryptCompat, rsaDecryptCompat, rsaEncryptCompat, sha1Compat, sha256Compat, sha512Compat } from '../shared/compat.uts' function toNumberArray(source : Uint8Array) : number[] { const output = [] as number[] let index = 0 while (index < source.length) { output.push(source[index]) index += 1 } return output } function fromNumberArray(source : number[]) : Uint8Array { const output = new Uint8Array(source.length) let index = 0 while (index < source.length) { output[index] = source[index] & 0xff index += 1 } return output } function unwrapString(value : string | null, message : string) : string { if (value == null) { throw new Error(message) } return value } function unwrapNumberArray(value : number[] | null, message : string) : number[] { if (value == null) { throw new Error(message) } return value } function unwrapBundle(value : NativeRsaBundle | null, message : string) : NativeRsaBundle { if (value == null) { throw new Error(message) } return value } export function defaultTextCipherOptions() : CryptoTextCipherOptions { return createDefaultTextCipherOptions() } export function defaultByteCipherOptions() : CryptoByteCipherOptions { return createDefaultByteCipherOptions() } export function defaultTripleDesOptions() : CryptoTripleDesOptions { return createDefaultTripleDesOptions() } export function defaultDesOptions() : CryptoDesOptions { return createDefaultDesOptions() } export function describeCryptoRuntime() : CryptoRuntimeSnapshot { return buildRuntimeSnapshot('iOS', 'CommonCrypto', true, true) } export function encodeText(codec : CryptoCodecKind, plainText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.encodeCodec(codec, plainText), '?'), '编码失败') } export function decodeText(codec : CryptoCodecKind, encodedText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.decodeCodec(codec, encodedText), '?'), '解码失败') } export function digestText(kind : CryptoDigestKind, plainText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.digestHex(kind, plainText), '?'), '摘要失败') } export function signText(kind : CryptoMacKind, secretText : string, plainText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.hmacHex(kind, secretText, plainText), '?'), 'HMAC失败') } export function aesEncryptText(secretText : string, plainText : string, options : CryptoTextCipherOptions | null) : string { const actual = normalizeTextCipherOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.aesEncryptText(secretText, plainText, actual.mode, actual.padding, actual.ivText, actual.keyLength), '?'), 'AES加密失败') } export function aesDecryptText(secretText : string, cipherText : string, options : CryptoTextCipherOptions | null) : string { const actual = normalizeTextCipherOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.aesDecryptText(secretText, cipherText, actual.mode, actual.padding, actual.ivText, actual.keyLength), '?'), 'AES解密失败') } export function aesEncryptBytes(secretBytes : Uint8Array, plainBytes : Uint8Array, options : CryptoByteCipherOptions | null) : Uint8Array { const actual = normalizeByteCipherOptions(options) const response = unwrapNumberArray(UTSiOS.try(NativeCipherCore.aesEncryptBytes(toNumberArray(secretBytes), toNumberArray(plainBytes), actual.mode, actual.padding, actual.ivBytes == null ? null : toNumberArray(actual.ivBytes), actual.keyLength), '?'), 'AES字节加密失败') return fromNumberArray(response) } export function aesDecryptBytes(secretBytes : Uint8Array, cipherBytes : Uint8Array, options : CryptoByteCipherOptions | null) : Uint8Array { const actual = normalizeByteCipherOptions(options) const response = unwrapNumberArray(UTSiOS.try(NativeCipherCore.aesDecryptBytes(toNumberArray(secretBytes), toNumberArray(cipherBytes), actual.mode, actual.padding, actual.ivBytes == null ? null : toNumberArray(actual.ivBytes), actual.keyLength), '?'), 'AES字节解密失败') return fromNumberArray(response) } export function tripleDesEncryptText(secretText : string, plainText : string, options : CryptoTripleDesOptions | null) : string { const actual = normalizeTripleDesOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.tripleDesEncryptText(secretText, plainText, actual.mode, actual.ivText), '?'), '3DES加密失败') } export function tripleDesDecryptText(secretText : string, cipherText : string, options : CryptoTripleDesOptions | null) : string { const actual = normalizeTripleDesOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.tripleDesDecryptText(secretText, cipherText, actual.mode, actual.ivText), '?'), '3DES解密失败') } export function desEncryptText(secretText : string, plainText : string, options : CryptoDesOptions | null) : string { const actual = normalizeDesOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.desEncryptText(secretText, plainText, actual.mode, actual.padding, actual.ivText), '?'), 'DES加密失败') } export function desDecryptText(secretText : string, cipherText : string, options : CryptoDesOptions | null) : string { const actual = normalizeDesOptions(options) return unwrapString(UTSiOS.try(NativeCipherCore.desDecryptText(secretText, cipherText, actual.mode, actual.padding, actual.ivText), '?'), 'DES解密失败') } export function rc4EncryptText(secretText : string, plainText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.rc4EncryptToHex(secretText, plainText), '?'), 'RC4加密失败') } export function rc4DecryptText(secretText : string, cipherHexText : string) : string { return unwrapString(UTSiOS.try(NativeCipherCore.rc4DecryptFromHex(secretText, cipherHexText), '?'), 'RC4解密失败') } export function createRsaPair(keySize : number) : CryptoRsaPair { const bundle = unwrapBundle(UTSiOS.try(NativeCipherCore.createRsaBundle(keySize), '?'), 'RSA密钥生成失败') return { publicKey: bundle.publicKey, privateKey: bundle.privateKey } as CryptoRsaPair } export function rsaEncryptText(publicKey : string, plainText : string, outputKind : RsaOutputKind | null) : string { return unwrapString(UTSiOS.try(NativeCipherCore.rsaEncrypt(publicKey, plainText, resolveHexOutput(outputKind) ? 'hex' : 'base64'), '?'), 'RSA加密失败') } export function rsaDecryptText(privateKey : string, cipherText : string, outputKind : RsaOutputKind | null) : string { return unwrapString(UTSiOS.try(NativeCipherCore.rsaDecrypt(privateKey, cipherText, resolveHexOutput(outputKind) ? 'hex' : 'base64'), '?'), 'RSA解密失败') } function compatBridge() : CompatBridge { return createCompatBridge( (codec : CryptoCodecKind, plainText : string) : string => encodeText(codec, plainText), (codec : CryptoCodecKind, encodedText : string) : string => decodeText(codec, encodedText), (kind : CryptoDigestKind, plainText : string) : string => digestText(kind, plainText), (kind : CryptoMacKind, secretText : string, plainText : string) : string => signText(kind, secretText, plainText), (secretText : string, plainText : string, options : CryptoTextCipherOptions | null) : string => aesEncryptText(secretText, plainText, options), (secretText : string, cipherText : string, options : CryptoTextCipherOptions | null) : string => aesDecryptText(secretText, cipherText, options), (secretBytes : Uint8Array, plainBytes : Uint8Array, options : CryptoByteCipherOptions | null) : Uint8Array => aesEncryptBytes(secretBytes, plainBytes, options), (secretBytes : Uint8Array, cipherBytes : Uint8Array, options : CryptoByteCipherOptions | null) : Uint8Array => aesDecryptBytes(secretBytes, cipherBytes, options), (secretText : string, plainText : string, options : CryptoDesOptions | null) : string => desEncryptText(secretText, plainText, options), (secretText : string, cipherText : string, options : CryptoDesOptions | null) : string => desDecryptText(secretText, cipherText, options), (keySize : number) : CryptoRsaPair => createRsaPair(keySize), (publicKey : string, plainText : string, outputKind : RsaOutputKind | null) : string => rsaEncryptText(publicKey, plainText, outputKind), (privateKey : string, cipherText : string, outputKind : RsaOutputKind | null) : string => rsaDecryptText(privateKey, cipherText, outputKind), (secretText : string, plainText : string) : string => rc4EncryptText(secretText, plainText), (secretText : string, cipherHexText : string) : string => rc4DecryptText(secretText, cipherHexText) ) } export function base64Encode(input : string) : string { return base64EncodeCompat(compatBridge(), input) } export function base64Decode(input : string) : string { return base64DecodeCompat(compatBridge(), input) } export function md5(input : string) : string { return md5Compat(compatBridge(), input) } export function sha1(input : string) : string { return sha1Compat(compatBridge(), input) } export function sha256(input : string) : string { return sha256Compat(compatBridge(), input) } export function sha512(input : string) : string { return sha512Compat(compatBridge(), input) } export function hmacSha1(key : string, data : string) : string { return hmacSha1Compat(compatBridge(), key, data) } export function hmacSha256(key : string, data : string) : string { return hmacSha256Compat(compatBridge(), key, data) } export function hmacSha512(key : string, data : string) : string { return hmacSha512Compat(compatBridge(), key, data) } export function aesEncrypt(key : string, data : string, mode : string = 'ECB', iv : string | null = null, keySize : number | null = 16) : string { return aesEncryptCompat(compatBridge(), key, data, mode, iv, keySize) } export function aesDecrypt(key : string, data : string, mode : string = 'ECB', iv : string | null = null, keySize : number | null = 16) : string { return aesDecryptCompat(compatBridge(), key, data, mode, iv, keySize) } export function aesEncrypt2(key : Uint8Array, data : Uint8Array, mode : string = 'ECB', iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { return aesEncryptBytesCompat(compatBridge(), key, data, mode, iv, keySize) } export function aesDecrypt2(key : Uint8Array, data : Uint8Array, mode : string = 'ECB', iv : Uint8Array | null = null, keySize : number | null = 16) : Uint8Array { return aesDecryptBytesCompat(compatBridge(), key, data, mode, iv, keySize) } export function desEncrypt(key : string, data : string, mode : string = 'ECB', iv : string | null = null) : string { return desEncryptCompat(compatBridge(), key, data, mode, iv) } export function desDecrypt(key : string, data : string, mode : string = 'ECB', iv : string | null = null) : string { return desDecryptCompat(compatBridge(), key, data, mode, iv) } export function generateRSAKeyPair(keySize : number = 2048) : CryptoRsaPair { return generateRsaKeyPairCompat(compatBridge(), keySize) } export function rsaEncrypt(publicKey : string, data : string) : string { return rsaEncryptCompat(compatBridge(), publicKey, data) } export function rsaDecrypt(privateKey : string, data : string) : string { return rsaDecryptCompat(compatBridge(), privateKey, data) } export function rc4Encrypt(key : string, data : string) : string { return rc4EncryptCompat(compatBridge(), key, data) } export function rc4Decrypt(key : string, data : string) : string { return rc4DecryptCompat(compatBridge(), key, data) } export function useCrypto() : CompatCrypto { return createCompatCrypto(compatBridge()) }