Retrieve issuer name from certificate by SecCertificate - ios

I have a certificate file. SecCertificate object is created correctly.
let data = try? Data(contentsOf: fileUrl!)
let certificate = SecCertificateCreateWithData(nil, data! as CFData)
▿ Optional<SecCertificateRef>
- some : <cert(0x7fec5d608250) s: www.google.com i: Avast trusted CA>
// I can get Subject name by
SecCertificateCopySubjectSummary(certificate!)! as String
// I tried printing SecCertificateCopyNormalizedIssuerSequence
var data1 = SecCertificateCopyNormalizedIssuerSequence(certificate!)! as Data
print(String(data: data1, encoding: .utf8))
Optional("0h1\u{0B}0\t\u{06}\u{03}U\u{04}\u{06}\u{13}\u{02}CZ1\u{0F}0\r\u{06}\u{03}U\u{04}\u{08}\u{0C}\u{06}Prague1\u{0E}0\u{0C}\u{06}\u{03}U\u{04}\n\u{0C}\u{05}AVAST1\u{1D}0\u{1B}\u{06}\u{03}U\u{04}\u{0B}\u{0C}\u{14}Software Development1\u{19}0\u{17}\u{06}\u{03}U\u{04}\u{03}\u{0C}\u{10}Avast trusted CA")
But I need to get issuers name info like common name or organisation(like i from SecCertificateRef in above example) using SecCertificate.h
Thanks.

Related

iOS CryptoSwift AES Encryption to Python Decryption works - but not the inverse

I am using CryptoSwift 1.4.1, iOS 15.2, PyCryptodome 3.12.0, and XCode 13.2.1 to encrypt small string messages that I send to a Raspberry Pi Linux Device over BLE. It works when iOS encrypts the message and sends it to the Raspberry Pi. The Pi can successfully decrypt it. Now I want to do the inverse, encrypt a message on the Pi and have the iOS App read and decrypt it. This, however is not working and the decrypted value is the not the message I encrypted on the Pi.
Working iOS encryption:
func aesEncrypt(stringToEncrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
let data = stringToEncrypt.data(using: String.Encoding.utf8)
let encrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).encrypt((data?.bytes)!)
return encrypted.toHexString()
}
let ivString = "4198816658388141"
let keyString = "9004786896524916"
let key = [UInt8](keyString.utf8)
let iv = [UInt8](ivString.utf8)
let encryptedSsid = try! aesEncrypt(stringToEncrypt: ssid!, key: key, iv: iv)
Working Raspberry Pi decryption in Python:
KEY = b'9004786896524916'
IV = b'4198816658388141'
MODE = AES.MODE_CFB
def decrypt(key, iv, encrypted_text):
logger.info(f"Encrypted: {encrypted_text}")
aes = AES.new(key, MODE, iv, segment_size=128)
encrypted_text_bytes = binascii.a2b_hex(encrypted_text)
decrypted_text = aes.decrypt(encrypted_text_bytes).decode("utf-8")
logger.info(f"Decrypted: {decrypted_text}")
return decrypted_text
I tried to encrypt a message on the Pi with the following code:
KEY = b'9004786896524916'
IV = b'4198816658388141'
MODE = AES.MODE_CFB
def encrypt(key, decrypted_text):
# Create cipher object and encrypt the data
logger.info(f"Decrypted: {decrypted_text}")
cipher = AES.new(key, MODE, segment_size=128) # Create a AES cipher object with the key using the mode CBC
#encrypted_text = cipher.encrypt(pad(decrypted_text, AES.block_size)) # Pad the input data and then encrypt
encrypted_text = cipher.encrypt(decrypted_text) # Pad the input data and then encrypt
logger.info(f"Encrypted: {encrypted_text}")
return encrypted_text
...
encrypt(KEY, returnString('utf-8'))
However, the iOS App fails to decrypt it properly with this method:
func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
let data = stringToDecrypt.data(using: String.Encoding.utf8)
let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt((data?.bytes)!)
return decrypted.toHexString()
}
let ivString = "4198816658388141"
let keyString = "9004786896524916"
let key = [UInt8](keyString.utf8)
let iv = [UInt8](ivString.utf8)
var message = try! aesDecrypt(stringToDecrypt: charString, key: key, iv: iv)
How can I get decryption to work properly in the iOS App when a message is encrypted on the Pi?
In the encrypt() method the IV is not considered. As in aesEncrypt(), the IV must be passed and used when creating the AES object.
Furthermore there are bugs in the encoding: The plaintext must be UTF8 encoded and the ciphertext must be hex encoded:
from Crypto.Cipher import AES
import binascii
def encrypt(key, iv, plaintext):
cipher = AES.new(key, MODE, iv, segment_size=128)
plaintext_bytes = plaintext.encode("utf-8")
ciphertext = cipher.encrypt(plaintext_bytes)
ciphertext_hex = binascii.b2a_hex(ciphertext)
return ciphertext_hex
This function is the counterpart to decrypt(), i.e. encrypt() can be used to generate a ciphertext which can be decrypted with decrypt() (or aesDecrypt()).
In the iOS code there are two bugs, both concerning the encoding: The ciphertext must not be UTF8 encoded, but hex decoded. And the decrypted data must not be hex encoded, but UTF-8 decoded.
A possible fix is:
func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
let data = Array<UInt8>(hex: stringToDecrypt)
let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt(data)
return String(bytes: decrypted, encoding: .utf8)!
}
This function is the counterpart to aesEncrypt(), i.e. aesDecrypt() can be used to decrypt a ciphertext generated with aesEncrypt() (or encrypt()).
Regarding security: A static IV is insecure. Instead, the IV should be randomly generated for each encryption. Since the (non-secret IV) is needed for decryption, it is passed along with the ciphertext (typically concatenated).

I received a response from the sever I wanted to decode it before I use it further

I have a string received from the server and I was trying to decode the string with padding but it is throwing nil as result. I tried codes that are available in stack overflow but of no use. Help will be highly appreciated.
I tried with base64 encoded with ignore unknown characters option and padding, still it throws nil.
let pem = "MIICyjCCAjOgAwIBAgIDBJPhMA0GCSqGSIb3DQEBBQUAMHsxEjAQBgNVBAMTCVJvb3RjZXJ0MTESMBAGA1UECRMJYmVsbGFuZHVyMQswCQYDVQQIEwJrYTEPMA0GA1UEERMGODg4ODg4MQwwCgYDVQQLEwNlc3MxGDAWBgNVBAoTD2VtdWRocmEgbGltaXRlZDELMAkGA1UEBhMCaW4wHhcNMTkwNzExMTAzNzM4WhcNMjgxMjI2MTAzNzM4WjB0MREwDwYDVQQDEwhBdmFkaGVzaDEMMAoGA1UECRMDYnRtMQswCQYDVQQIEwJrYTEPMA0GA1UEERMGODc4Nzg3MQwwCgYDVQQLEwNlc3MxGDAWBgNVBAoTD2VtdWRocmEgbGltaXRlZDELMAkGA1UEBhMCaW4wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMDAm7W3nc3hyyAhG8RBCSmlSDzcU/C39dPEFPq3N0JpSghMojnZg0jnfwXCvWqtPhlTYEdVLSXRehmQpS2v/FN8wkqZoVaKHNQE1UJnzPbyjfTlQA20nlCNVTNBQ70rWYzfuuFhliUBycGbYaIE/VGk354AEdXipLklCPf7PsgZAgMBAAGjYzBhMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUkdq9ZIGVtD0x6k6hO7PdFMidh/QwHQYDVR0OBBYEFDwUkx0+5e1xTcavaVBpvREel/hZMAsGA1UdDwQEAwIBzjANBgkqhkiG9w0BAQUFAAOBgQBIDy2MjWWsZC9G1k3DFYyP2/jsj/xzKyQh2e5YrnxIGtK5jBRKZe3JOuq1wxMzRfzd22lnSyKzf4dKMp2ADXJnNQrB/aafGs9nf+FXuIomquZHoNGrThfSyB/tre8T3dMWRiUdYy74XL2wvQb6tVHPQ/UEPSYOyf3XDSnzpgtjmw=="
let decodedData = NSData(base64Encoded: dataStr, options: .ignoreUnknownCharacters)
let length = dataStr.count
dataStr = dataStr.padding(toLength: length + (4 - length % 4) % 4, withPad: "=", startingAt: 0)`
It has to give some decoded data with which I can create a certificate because the response is in the format of .cert.
A certificate is not a string. You cannot create a string from the raw Data.
You can decode the base64 encoded string simply with
let decodedData = Data(base64Encoded: dataStr)
Notes:
Don't use NSData in Swift.
The ignoreUnknownCharacters is not needed.
The padding is wrong. It's only required when encoding the data and the base64 related API of String and Data adds the = characters automatically.
May be It will Help
For Image I am doing like this
I am converting UIImage To data and Converting That data to base64EncodedString
let imageData = UIimage.pngData()
//encode string
let imgBase64Str = imageData?.base64EncodedString(options: .lineLength64Characters) ?? ""
//decoding string to data
let decodedData = Data(base64Encoded: imgBase64Str, options: .ignoreUnknownCharacters)

How to get SecIdentity after SecCertificateCreateWithData and SecItemAdd?

I was given a .cer file which needs to be used to connect with the server properly. At first SecCertificateCreateWithData crashed, so after research, I ended up converting .cer file to der format (openssl x509 -in cert.cer -outform der -out certder.der), and then iOS seemed to accept it.
I need to get SecIdentity object, however, there seems to be a problem:
let cerPath = Bundle.main.path(forResource: "certder", ofType: "der")
let data: NSData = try! Data(contentsOf: URL(fileURLWithPath: cerPath!)) as! NSData
let cert: SecCertificate = SecCertificateCreateWithData(nil, data)!
let params : [String: Any] = [
kSecClass as String : kSecClassCertificate,
kSecValueRef as String : cert,
kSecAttrLabel as String: "label1",
]
SecItemDelete(params as CFDictionary)
let status = SecItemAdd(params as CFDictionary, nil)
print("status1: \(status)")
let query: [String: Any] = [
kSecClass as String : kSecClassIdentity,
kSecReturnRef as String: true,
kSecAttrLabel as String: "label1"
]
var secIdentity: SecIdentity?
var extractedData: AnyObject?
let status2 = SecItemCopyMatching(query as NSDictionary, &extractedData)
print("status2: \(status2)")
if (status2 == errSecSuccess) {
print("success")
secIdentity = extractedData as! SecIdentity?
}
Log:
status1: 0
status2: -25300. Error -25300 is errSecItemNotFound
Here is how info of that given certificate looks like:
openssl x509 -in cert.cer -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1465898828 (0x575fd74c)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=LT, L=NamePurposelyHidden, O=NamePurposelyHidden, OU=NamePurposelyHidden, CN=NamePurposelyHidden
Validity
Not Before: Aug 9 08:21:03 2014 GMT
Not After : Jul 27 08:21:03 2064 GMT
Subject: C=LT, L=NamePurposelyHidden, O=NamePurposelyHidden, OU=NamePurposelyHidden, CN=NamePurposelyHidden
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b6:26:54:85:05:15:bd:2f:af:39:c0:91:41:05:
d2:35:74:bf:d2:e5:35:2d:3d:21:60:15:6b:d9:f6:
66:2b:02:29:c9:94:8b:3c:36:af:f8:5a:05:0f:21:
25:7d:90:5b:ab:70:f5:85:e8:ce:8a:60:2b:a4:61:
36:a8:b9:16:f6:79:7b:e1:1f:37:83:5b:fd:18:db:
70:7a:dd:79:3b:74:0d:4b:4f:4d:49:8c:79:0b:8c:
c1:2e:7c:4c:62:ae:b3:e4:b5:cf:4b:20:2c:98:20:
4a:4c:dd:49:67:99:7f:c1:dd:39:4d:be:8c:b7:6a:
b8:e6:c3:e3:a8:03:21:ec:a3:c8:e4:46:d7:e6:d4:
83:4a:5a:d7:a1:35:6f:54:72:96:b2:52:54:37:d4:
b4:62:f8:07:eb:27:d5:f0:42:0f:5a:3a:b8:ae:78:
38:73:e4:b5:7c:d1:6b:e4:61:6e:fd:df:c8:03:a4:
8d:fe:d3:92:98:df:30:fb:e1:03:45:cb:dd:6a:ca:
50:25:b2:a6:4b:4a:64:e0:79:a6:ef:35:53:df:d9:
48:16:f8:39:08:94:9b:8e:f0:74:01:ae:76:46:9c:
9c:a3:ec:70:45:24:44:96:3d:b4:06:51:2e:1e:dd:
4d:72:09:0d:9d:f1:11:08:9d:24:4b:5c:3e:79:0b:
b9:c7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
AE:95:DF:CD:E0:D9:BB:D1:8E:CD:15:86:98:9B:04:35:D7:E6:96:44
Signature Algorithm: sha256WithRSAEncryption
61:d3:98:46:a9:53:db:fc:a9:3b:db:40:40:63:55:7c:66:74:
35:82:83:c8:19:4a:89:ae:bd:1b:5c:26:8e:20:f9:5b:db:aa:
0c:4c:99:4e:28:3b:51:00:33:96:5f:22:40:c1:c1:c8:ed:70:
d7:f7:3e:aa:ec:f9:0e:bb:ec:f8:17:12:c1:49:f6:02:0d:73:
57:39:48:5d:ad:8f:e5:e9:3b:b1:f8:1d:d4:7e:cf:58:d5:78:
73:9c:56:3b:bb:3a:25:36:c8:3b:b8:ba:90:97:6e:28:51:5d:
63:23:3e:90:7d:87:61:13:03:c5:27:1b:51:55:c0:17:76:18:
1a:74:6d:f9:2c:c8:f1:7a:89:64:41:fc:3b:7b:82:4f:e3:e8:
5d:02:40:3a:d5:81:f3:38:de:aa:79:53:1a:d2:a3:60:59:94:
8c:bd:62:bb:6d:70:da:0d:22:3e:9d:e0:fa:5d:20:87:ce:16:
f0:53:f4:b7:1d:c7:b3:59:64:ba:8a:73:75:bc:7f:61:cb:14:
d4:9f:34:3f:bd:b1:06:0c:62:f6:1f:b4:d2:15:38:61:bd:2c:
44:94:1c:e1:88:f4:d2:fc:42:d7:6d:ed:d6:4e:a2:b7:67:20:
01:7a:87:39:3b:4c:2b:3c:ef:3c:15:54:1d:cc:00:30:9c:cc:
e2:4f:71:98

CryptoSwift - Converting UInt8 array to String resolves as nil

(Xcode 8, Swift 3)
Using the CryptoSwift library, I am wanting to encrypt a string and store it in coredata, for some reason, cipherstring results as nil, despite ciphertext having 128 values:
let aes = try AES(key: pw, iv: nil, blockMode: .CBC, padding: PKCS7())
let ciphertext = try aes.encrypt(token.utf8.map({$0}))
let cipherstring = String(bytes:ciphertext, encoding: String.Encoding.utf8) // always nil
I have also tried using the data: overload of string, convering the byte array to a data object. This also results as nil.
EDIT/SOLUTION (per Rob Napier's answer)
// encode/convert to string
let aes = try AES(key: pw, iv: nil, blockMode: .CBC, padding: PKCS7())
let ciphertext = try aes.encrypt(token.utf8.map({$0}))
let cipherstring = Data(bytes: ciphertext).base64EncodedString()
// decode
let aes = try AES(key: pw, iv: nil, blockMode: .CBC, padding: PKCS7())
let cipherdata = Data(base64Encoded: cipherstring)
let ciphertext = try aes.decrypt(cipherdata!.bytes)
let token = String(bytes:ciphertext, encoding:String.Encoding.utf8)
AES encrypted data is a random bunch of bytes. If you pick a random bunch of bytes, it is very unlikely to be valid UTF-8. If you have data and you want a string, you need to encode the data somehow. The most popular way to do that is Base-64. See Data.base64EncodedString() for a tool to do that. You'll also need Data(base64Encoded:) to reconstruct your Data from the String later.

iOS - Use GCDAsyncSocket to send something to server have some error

I have two client ,one is iOS(Client A) ,another is Jave (Client B) , Client A use for sender and the Client B is receive the data from Client A and print it in console , now I send some String(String and JsonString) to client B , Client B can receieve the message form Client A ,but the console print incomplete
This is my step
1、I define a NSDictionary in iOS
let dict:NSDictionary = ["type":type,"x":point.x,"y":point.y]
2、convent it to json string and append some string in json String
var error:NSError?
let data = NSJSONSerialization.dataWithJSONObject(dict,options:NSJSONWritingOptions.PrettyPrinted, error: &error)
var str = NSString(data: data!, encoding: NSUTF8StringEncoding)
var newStr = return "\(toPort)#\(str!)"
then I print it in iOS console ,It works fine
3、 I convert the string to NSData
let data = newStr.dataUsingEncoding(NSUTF8StringEncoding)
4、send the NSData to server
self.socket!.writeData(data!, withTimeout: self.timeout, tag: 0)
5、only have { displayed in client B ,what happen?
then I try to use jave to achieve the client A , and it works fine in client B
I solved it
1、remove all \n in str
2、use
var newStr = return "\(toPort)#\(str!)\n"
instand of
var newStr = return "\(toPort)#\(str!)"

Resources