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