//
//  Encrypt.h
//  MicroLifeDeviceSDK
//
//  Created by 吳憲有 on 2023/8/17.
//

#import <Foundation/Foundation.h>
#import <Security/Security.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCrypto.h>

NS_ASSUME_NONNULL_BEGIN

@interface Encrypt : NSObject

#pragma mark - MD5
+ (NSString *)MD5:(NSString *)str;

#pragma mark - SHA1
+ (NSString *)SHA1:(NSString *)str;

#pragma mark - SHA256
+ (NSString *)SHA256:(NSString *)str;

#pragma mark - SHA512
+ (NSString *)SHA512:(NSString *)str;

#pragma mark - RandomIVF
+ (NSData *)generateRandomIVForBlockSize:(size_t)blockSize;

#pragma mark - Base64加密/解密
/// Base64加密（NSString）
/// - Parameter string: <#string description#>
+ (NSString *)Base64EncodedString:(NSString *)string;

/// Base64加密（NSData）
/// - Parameter sourceData: <#sourceData description#>
+ (NSString *)Base64EncodingWithData:(NSData *)sourceData;

/// Base64解密（NSString）
/// - Parameter string: <#string description#>
+ (NSString *)Base64DecodedString:(NSString *)string;

/// Base64解密（NSData）
/// - Parameter sourceString: <#sourceString description#>
+ (NSData *)Base64EncodingWithString:(NSString *)sourceString;

#pragma mark - DES加密解密
/// DES加密（NSData）
/// - Parameters:
///   - data: <#data description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSData *)DESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

///  DES加密（NSString）
/// - Parameters:
///   - string: <#string description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSString *)DESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

/// DES解密（NSData）
/// - Parameters:
///   - data: <#data description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSData *)DESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

/// DES解密（NSString）
/// - Parameters:
///   - string: <#string description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSString *)DESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

#pragma mark - AES加密解密
/// AES加密（NSData）
/// - Parameters:
///   - data: <#data description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSData *)AESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

/// AES加密（NSString）
/// - Parameters:
///   - string: <#string description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSString *)AESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

/// AES解密（NSData）
/// - Parameters:
///   - data: <#data description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSData *)AESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

/// AES解密（NSString）
/// - Parameters:
///   - string: <#string description#>
///   - keyString: <#keyString description#>
///   - ivString: <#ivString description#>
+ (NSString *)AESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSString * _Nullable)ivString;

#pragma mark - ECC加密解密
/// 生成ECC公私鑰對
///
/// @discussion 1. 本方法會默認將公私鑰對存入KeyChain
/// @discussion 2. 私鑰的訪問控制（kSecAttrAccessControl）設置為系統默認值
/// @param identifier 此公私鑰對的唯一標識
/// @return 返回公鑰的NSData對象
+ (NSData *)generateECCKeyPairWithIdentifier:(NSString *)identifier;

/// 查詢ECC公鑰
/// @param identifier 唯一標識，用於查找對應的公鑰，此值應與生成時相同
/// @return ECC公鑰的NSData對象
+ (NSData *)queryPublicKeyWithIdentifier:(NSString *)identifier;

/// 使用私鑰對數據進行簽名
/// @param source 需要簽名的數據NSData對象
/// @param identifier 唯一標識，用於查找對應的私鑰，此值應與生成時相同
/// @return 使用私鑰簽名後的數據
+ (NSData *)signPrivateKeyWithSource:(NSData *)source identifier:(NSString *)identifier;

/// 刪除當前App下所有的KeyChain數據，慎用！慎用！慎用！
///
/// @discussion 建議僅在開發、調試過程中使用
+ (void)deleteAllKeyChain;

/// 刪除指定ECC公私鑰對
/// @param identifier 此公私鑰對的唯一標識
+ (void)deleteECCKeyPairIdentifier:(NSString *)identifier;

/// 生成ECC公私鑰對
/// @param identifier 此公私鑰對的唯一標識
/// @return 返回公私鑰的SecKeyRef對象數組，數組第1項為公鑰，第2項為私鑰
+ (NSArray *)generateECCKeyPairSecKeyRefWithIdentifier:(NSString *)identifier;

/// 查詢ECC公鑰
/// @param identifier 唯一標識，用於查找對應的公鑰，此值應與生成時相同
/// @return ECC公鑰的SecKeyRef對象
+ (SecKeyRef _Nullable)queryPublicKeySecKeyRefWithIdentifier:(NSString *)identifier;

/// 查詢ECC私鑰
/// @param identifier 唯一標識，用於查找對應的私鑰，此值應與生成時相同
/// @return ECC私鑰的SecKeyRef對象
+ (SecKeyRef _Nullable)queryPrivateKeySecKeyRefWithIdentifier:(NSString *)identifier;

/// 使用私鑰對數據進行簽名
/// @param source 需要簽名的數據NSData對象
/// @param privateKey 私鑰的SecKeyRef對象
/// @return 使用私鑰簽名後的數據
+ (NSData *)signWithSource:(NSData *)source privateKey:(SecKeyRef)privateKey;

/// 使用私鑰對數據進行驗簽
/// @param source 簽名前的數據的NSData對象
/// @param signature 已簽名的數據的NSData對象
/// @param publicKey 私鑰的SecKeyRef對象
/// @return 是否通過驗簽，YES驗簽通過，NO驗簽不通過
+ (BOOL)verifyWithSource:(NSData *)source signature:(NSData *)signature publicKey:(SecKeyRef)publicKey;

@end

NS_ASSUME_NONNULL_END
