14 C
London
Friday, October 20, 2023

ios – RSA Encryption in Swift: Encrypted Knowledge However Not Decrypting Efficiently


I am within the means of implementing RSA encryption in my iOS mission. To realize this, I’ve created a RSAEncryption helper class, which features a generateRSAKeyPair(keySize: Int) methodology for producing each publicKey and privateKey.

Though I can efficiently generate the keys utilizing the tactic talked about above, I encounter an error when making an attempt to encrypt information utilizing the publicKey and subsequently decrypt it utilizing the privateKey.

Error decrypting information:" Error Area=NSOSStatusErrorDomain Code=-50 "RSAdecrypt flawed enter (err -27)" UserInfo={numberOfErrorsDeep=0, NSDescription=RSAdecrypt flawed enter (err -27)}

Right here is my code:

enum RSAError: Error {
    case base64Error
    case stringToDataConversionFailed
    case keyGenerationFailed(error: Error?)
}

class RSAEncryption {
    static let shared = RSAEncryption()
    
    func generateRSAKeyPair(keySize: Int = 2048, tag: String = "") throws -> (privateKey: SecKey?, publicKey: SecKey?) {
        guard let tagData = tag.information(utilizing: .utf8) else {
            throw RSAError.stringToDataConversionFailed
        }
        
        let isPermanent = false
        let attributes: [CFString: Any] = [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeySizeInBits: keySize,
            kSecPrivateKeyAttrs: [
                kSecAttrIsPermanent: isPermanent,
                kSecAttrApplicationTag: tagData,
                kSecAttrKeyType: kSecAttrKeyTypeRSA // Add this line
            ],
            kSecPublicKeyAttrs: [
                kSecAttrIsPermanent: isPermanent,
                kSecAttrApplicationTag: tagData,
                kSecAttrKeyType: kSecAttrKeyTypeRSA // Add this line
            ]
        ]
        
        var error: Unmanaged<CFError>?
        guard let privKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error),
              let pubKey = SecKeyCopyPublicKey(privKey) else {
            throw RSAError.keyGenerationFailed(error: error?.takeRetainedValue() ?? nil)
        }
        
        return (privateKey: privKey, publicKey: pubKey)
    }
}

extension RSAEncryption {
    // Encrypt utilizing SecKey
    func encryptSec(information: Knowledge, publicKey: SecKey) -> Knowledge? {
        var error: Unmanaged<CFError>?
        if let encryptedData = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionOAEPSHA1, information as CFData, &error) as Knowledge? {
            debugPrint("Encrypted information:n", encryptedData.base64EncodedString())
            return encryptedData as Knowledge
        } else {
            if let error = error?.takeRetainedValue() {
                debugPrint("Encrypted information:", error)
            } else {
                debugPrint("Unknown error encrypting information")
            }
        }
        return nil
    }
    // Decrypt utilizing SecKey
    func decryptSec(information: Knowledge, privateKey: SecKey) -> Knowledge? {
        var error: Unmanaged<CFError>?
        if let decryptedData = SecKeyCreateDecryptedData(privateKey, .rsaEncryptionOAEPSHA1, information as CFData, &error) as Knowledge? {
            let decryptedString = String(information: decryptedData, encoding: .utf8)
            debugPrint("Decrypted information:", decryptedString ?? "Unable to decode as UTF-8")
            return decryptedData
        } else {
            if let error = error?.takeRetainedValue() {
                debugPrint("Error decrypting information:", error)
            } else {
                debugPrint("Unknown error decrypting information")
            }
        }
        return nil
    }
}

extension SecKey {
    
    func information() -> Knowledge? {
        var error: Unmanaged<CFError>?
        guard let keyData = SecKeyCopyExternalRepresentation(self, &error) as Knowledge? else {
            let error = error!.takeRetainedValue() as Error
            debugPrint(error)
            return nil
        }
        return keyData
    }
    
    func base64String() -> String {
        let derKey = self.addHeader()
        let base64 = base64Encode(derKey)
        return base64
    }
    
    personal func base64Encode(_ key: Knowledge) -> String {
        return key
            .base64EncodedString( choices: [.endLineWithLineFeed, .endLineWithCarriageReturn, .lineLength76Characters])
            .replacingOccurrences(of: "n", with: "")
    }
    
    personal func addHeader() -> Knowledge {
        var outcome = Knowledge()
        guard let derKey = self.information() else {
            debugPrint("ERROR: Creating PEM Failed")
            return outcome
        }
        
        let encodingLength: Int = encodedOctets(derKey.rely + 1).rely
        let OID: [UInt8] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
                            0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00]
        
        var builder: [UInt8] = []
        
        // ASN.1 SEQUENCE
        builder.append(0x30)
        
        // Total measurement, manufactured from OID + bitstring encoding + precise key
        let measurement = OID.rely + 2 + encodingLength + derKey.rely
        let encodedSize = encodedOctets(measurement)
        builder.append(contentsOf: encodedSize)
        outcome.append(builder, rely: builder.rely)
        outcome.append(OID, rely: OID.rely)
        builder.removeAll(keepingCapacity: false)
        
        builder.append(0x03)
        builder.append(contentsOf: encodedOctets(derKey.rely + 1))
        builder.append(0x00)
        outcome.append(builder, rely: builder.rely)
        // Precise key bytes
        outcome.append(derKey)
        return outcome
    }
    
    personal func encodedOctets(_ int: Int) -> [UInt8] {
        // Brief kind
        if int < 128 {
            return [UInt8(int)]
        }
        
        // Lengthy kind
        let i = (int / 256) + 1
        var len = int
        var outcome: [UInt8] = [UInt8(i + 0x80)]
        
        for _ in 0..<i {
            outcome.insert(UInt8(len & 0xFF), at: 1)
            len = len >> 8
        }
        
        return outcome
    }
}

Utilization:

import Safety

class ViewController: UIViewController {
    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
        let rsa = RSAEncryption.shared
        
        guard let publicKey = strive? rsa.generateRSAKeyPair(keySize: 2048).publicKey,
              let privateKey = strive? rsa.generateRSAKeyPair().privateKey
        else {
            return
        }
        guard let encrypted = rsa.encryptSec(information: "Hey World.!!".information(utilizing: .utf8)!, publicKey: publicKey) else {
            return
        }
        print("Pub: n", publicKey.base64String())
        print("Priv: n ", privateKey.base64String())
        
        guard let decrypted = rsa.decryptSec(information: encrypted, privateKey: privateKey) else {
            return
        }
        print(String(information: decrypted, encoding: .utf8))
    }
}

I’ve tried encryption and decryption each regionally and on-line, encountering the identical problem. Whereas I can efficiently encrypt information, the decryption course of constantly fails.

https://8gwifi.org/rsafunctions.jsp
https://www.devglan.com/online-tools/rsa-encryption-decryption

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here