Skip to content

Commit

Permalink
chore: ios encrypt 부분까지 성공
Browse files Browse the repository at this point in the history
  • Loading branch information
ko-devHong committed May 7, 2024
1 parent 581e568 commit 529e8ae
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 62 deletions.
2 changes: 1 addition & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function App() {
try {
const { publicKey } = await RNCryptoRsa.init();
setPublicString(publicKey);
console.log('@publicKey : ', publicKey);
// console.log('@publicKey : ', publicKey);
// console.log('privateKey : ', privateKey);
const encryptBase64String = await RNCryptoRsa.encrypt(
'hello world',
Expand Down
148 changes: 87 additions & 61 deletions ios/CryptoRsa.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CommonCrypto
import Security

extension String {

public var sha512: String {
let data = self.data(using: .utf8) ?? Data()
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
Expand All @@ -17,35 +17,37 @@ extension String {

@objc(CryptoRsa)
class CryptoRsa: NSObject {
let publicTag = "ko.dev.hong.rn.public.key"
let privateTag = "ko.dev.hong.rn.private.key"
let publicTag = "ko.dev.hong.rn.public"
let privateTag = "ko.dev.hong.rn.private"
let secKeyAlgorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1
static var privateKeyValue: SecKey?;

struct RuntimeError: LocalizedError {
let description: String

init(_ description: String) {
self.description = description
}

var errorDescription: String? {
description
}
}

func getKeyFromKeychain(tag: String) -> SecKey? {
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag,
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecReturnRef as String: true
kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag,
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecReturnRef as String: true,
kSecReturnData as String: kCFBooleanTrue ?? true
]

var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else {
print("Error retrieving key from keychain: \(status)")
return nil
print("Error retrieving key from keychain: \(status)")
return nil
}

return (item as! SecKey)
Expand All @@ -54,7 +56,7 @@ class CryptoRsa: NSObject {
func base64EncodeString(_ data: Data) -> String {
return data.base64EncodedString(options: .lineLength64Characters)
}

func base64Decode(_ string: String) -> Data? {
return Data(base64Encoded: string,options: .ignoreUnknownCharacters)
}
Expand Down Expand Up @@ -93,17 +95,17 @@ class CryptoRsa: NSObject {
pemCleaned = pemCleaned.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
pemCleaned = pemCleaned.replacingOccurrences(of: "\r\n", with: "")
pemCleaned = pemCleaned.replacingOccurrences(of: "\n", with: "")

guard let data = base64Decode(pemCleaned) else {
print("base64 decode faild")
return nil
}

let options: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
]

var error: Unmanaged<CFError>?
guard let publicKey = SecKeyCreateWithData(data as CFData, options as CFDictionary, &error) else {
if let error = error {
Expand All @@ -113,68 +115,89 @@ class CryptoRsa: NSObject {
}
return nil
}

return publicKey
}

@objc(generateKeys:withResolver:withRejecter:)
func generateKeys(keySize: Int,resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
let access = SecAccessControlCreateWithFlags(nil, // Use the default allocator
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.privateKeyUsage,
nil) // Ignore any error

let publicKeyParameters: [String: AnyObject] = [
kSecAttrIsPermanent as String: true as AnyObject,
kSecAttrAccessControl as String: access!,
kSecAttrApplicationTag as String: publicTag.data(using: .utf8)! as AnyObject
]
let privateKeyParameters: [String: AnyObject] = [
kSecAttrIsPermanent as String: true as AnyObject,
kSecAttrAccessControl as String: access!,
kSecAttrApplicationTag as String: privateTag.data(using: .utf8)! as AnyObject
]
let parameters: [String: AnyObject] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize as AnyObject,
kSecPublicKeyAttrs as String: publicKeyParameters as AnyObject,
kSecPrivateKeyAttrs as String: privateKeyParameters as AnyObject
]

var publicKey, privateKey: SecKey?
let status = SecKeyGeneratePair(parameters as CFDictionary, &publicKey, &privateKey)

guard status == errSecSuccess else {
print("Error generating key pair: \(status)")
return reject(nil, nil, RuntimeError("Error generating key pair: \(status)"))
}
// let access = SecAccessControlCreateWithFlags(nil, // Use the default allocator
//kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
// .privateKeyUsage,
// nil) // Ignore any error

let publicKeyParameters: [String: AnyObject] = [
kSecAttrIsPermanent as String: true as AnyObject,
// kSecAttrAccessControl as String: access!,
kSecAttrAccessible as String: kSecAttrAccessibleAlways,
kSecAttrApplicationTag as String: publicTag.data(using: .utf8)! as AnyObject
]
let privateKeyParameters: [String: AnyObject] = [
kSecAttrIsPermanent as String: true as AnyObject,
// kSecAttrAccessControl as String: access!,
kSecAttrAccessible as String: kSecAttrAccessibleAlways,
kSecAttrApplicationTag as String: privateTag.data(using: .utf8)! as AnyObject
]
let parameters: [String: AnyObject] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize as AnyObject,
kSecPublicKeyAttrs as String: publicKeyParameters as AnyObject,
kSecPrivateKeyAttrs as String: privateKeyParameters as AnyObject,
]

var publicKey, privateKey: SecKey?
if #available(iOS 10.0, *) {

var error: Unmanaged<CFError>?
privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error)

if privateKey == nil {
print("Error occured: keys weren't created")
return reject(nil, nil, RuntimeError("Error occured: keys weren't created"))
}

publicKey = SecKeyCopyPublicKey(privateKey!)

} else {
// Fallback on earlier versions

let status = SecKeyGeneratePair(parameters as CFDictionary, &publicKey, &privateKey)

guard status == errSecSuccess else {
print("Error generating key pair: \(status)")
return reject(nil, nil, RuntimeError("Error generating key pair: \(status)"))
}
}

let keys = ["publicKey": publicKeyToPemString(publicKey!), "privateKey": privateKeyToPemString(privateKey!)]

resolve(keys)
}

@objc(encrypt:withPublicKey:withResolver:withRejecter:)
func encrypt(message: String, pemString: String,resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
guard let data = message.data(using: .utf8) else { return reject(nil,nil,RuntimeError("Data is null")) }

guard let publicKey = pemStringToPublicKey(pemString) else {
return reject(nil,nil,RuntimeError("pemStringTopublicKey is null"))
}

guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, secKeyAlgorithm) else { return reject(nil,nil,RuntimeError("SecKeyIsAlgorithm not supported")) }
var error: Unmanaged<CFError>?

guard let cipherData = SecKeyCreateEncryptedData(publicKey,
secKeyAlgorithm,
data as CFData,
&error) as Data? else {
print("Encryption error: \((error?.takeRetainedValue())!)")
return reject(nil, nil, RuntimeError("Encryption error: \((error?.takeRetainedValue())!)"))
print("Encryption error: \((error?.takeRetainedValue())!)")
return reject(nil, nil, RuntimeError("Encryption error: \((error?.takeRetainedValue())!)"))
}

resolve(base64EncodeString(cipherData))
resolve(cipherData.base64EncodedString())
}

@objc(decrypt:withResolver:withRejecter:)
func decrypt(encryptedDataString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
func decrypt(encryptedDataString: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Any? {
guard let encryptedData = base64Decode(encryptedDataString) else {
print("base64Decode Faild")
return reject(nil,nil,RuntimeError("base64Decode Faild"))
Expand All @@ -184,20 +207,23 @@ class CryptoRsa: NSObject {
return reject(nil,nil,RuntimeError("Keychain Load failed"))
}
print("Load privateKey in KeyChain :", loadedPrivateKey)

guard SecKeyIsAlgorithmSupported(loadedPrivateKey, .decrypt, secKeyAlgorithm) else { return reject(nil,nil,RuntimeError("SecKeyIsAlgorithm not supported")) }

guard SecKeyIsAlgorithmSupported(loadedPrivateKey, .decrypt, secKeyAlgorithm) else {
reject(nil,nil,RuntimeError("SecKeyIsAlgorithm not supported"))
return nil
}
var error: Unmanaged<CFError>?

guard let clearData = SecKeyCreateDecryptedData(loadedPrivateKey,
secKeyAlgorithm,
encryptedData as CFData,
&error) as Data? else {
print("Decryption error: \((error?.takeRetainedValue())!)")
return reject(nil,nil,RuntimeError("SecKeyIsAlgorithm not supported"))
print("Decryption error: \((error?.takeRetainedValue())!)")
return reject(nil,nil,RuntimeError("SecKeyIsAlgorithm not supported"))

}

resolve(String(data: clearData, encoding: .utf8))
return resolve(String(data: clearData, encoding: .utf8))
}

@objc(getSHA512Text:withResolver:withRejecter:)
Expand All @@ -215,7 +241,7 @@ class CryptoRsa: NSObject {
print("Load privateKey in KeyChain :", loadedPrivateKey)
resolve(loadedPrivateKey)
}

@objc(getPublicKey:withRejecter:)
func getPublicKey(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) {
guard let loadedPublicKey = getKeyFromKeychain(tag: publicTag ) else {
Expand Down

0 comments on commit 529e8ae

Please sign in to comment.