I am working on an application on IOS and I need to be able to decrypt an element that has been encrypted with a public key, but I only know the modulus and the private exponent of the private key. How can I obtain the private key from these elements in IOS? In java, with the following code I can get the private key from these elements and I can decrypt the element.
final RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(MODULUS, PRIVATE_EXPONENT);
final KeyFactory factory = KeyFactory.getInstance("RSA");
final PrivateKey priv = factory.generatePrivate(privateSpec);
On ios, I got the following code, but it doesn't return the private key:
let smodulus = "00c35d6ac32d287dab681c78272931b60ca442bd4505e1b306432af92ef6e07bc3e4e24c2bc2dac69c94753390c3793b80734ef906520a96cafb146ce587ab383e78efc58c5ccf56b5084f3f9bc719e646a0361155ab56b7d71b49f1f90673383ea0fdb4a67900c0973930aa3bc7071c479b4a5d229fcab7ce22b84c1637d7e70b"
let sPrivateExponent = "1f2535700832fc55e73322b49b8ca14942a6a125efda1b805414f5c4d6f6d2c45828fb9bbe64c2651405db42a8e71ae54f7cb7969a5db5cc865aab41ac6f4f77deccb51496fe588f9dcd724a1d49cab96712621afc9c656c56dea011f8ab8e12a321fd62430902b15586a36093a6679e31b67017397da83b0992f5f816017701"
let sPublicExponent = "010001"
public static func getPrivateKey(smodulus: String, sPrivateExponent: String) -> SecKey? {
let pubExponent: [UInt8] = [1, 0, 1]
let exponent: [UInt8] = sPrivateExponent.hexaBytes
var modulus: [UInt8] = smodulus.hexaBytes
//modulus.insert(0x00, at: 0)
var modulusEncoded: [UInt8] = []
modulusEncoded.append(0x02)
modulusEncoded.append(contentsOf: lengthField(of: modulus))
modulusEncoded.append(contentsOf: modulus)
var exponentEncoded: [UInt8] = []
exponentEncoded.append(0x02)
exponentEncoded.append(contentsOf: lengthField(of: exponent))
exponentEncoded.append(contentsOf: exponent)
var sequenceEncoded: [UInt8] = []
sequenceEncoded.append(0x30)
sequenceEncoded.append(contentsOf: lengthField(of: (modulusEncoded + exponentEncoded)))
sequenceEncoded.append(contentsOf: (modulusEncoded + exponentEncoded))
let keyData = Data(bytes: sequenceEncoded)
// RSA key size is the number of bits of the modulus.
let keySize = (modulus.count * 8)
let attributes: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits as String: keySize
]
let privateKey = SecKeyCreateWithData(keyData as CFData, attributes as CFDictionary, nil)
return privateKey
}
private static func lengthField(of valueField: [UInt8]) -> [UInt8] {
var count = valueField.count
if count < 128 {
return [ UInt8(count) ]
}
// The number of bytes needed to encode count.
let lengthBytesCount = Int((log2(Double(count)) / 8) + 1)
// The first byte in the length field encoding the number of remaining bytes.
let firstLengthFieldByte = UInt8(128 + lengthBytesCount)
var lengthField: [UInt8] = []
for _ in 0..<lengthBytesCount {
// Take the last 8 bits of count.
let lengthByte = UInt8(count & 0xff)
// Add them to the length field.
lengthField.insert(lengthByte, at: 0)
// Delete the last 8 bits of count.
count = count >> 8
}
// Include the first byte.
lengthField.insert(firstLengthFieldByte, at: 0)
return lengthField
}
extension StringProtocol {
var hexaData: Data { .init(hexa) }
var hexaBytes: [UInt8] { .init(hexa) }
private var hexa: UnfoldSequence<UInt8, Index> {
sequence(state: startIndex) { startIndex in
guard startIndex < self.endIndex else { return nil }
let endIndex = self.index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex
defer { startIndex = endIndex }
return UInt8(self[startIndex..<endIndex], radix: 16)
}
}
}