Objective
A RSA-4096 key pair is generated and the public key shall be send in order to ecrypt some payload.
The microservice executing the encryption is written in Java 17.
Note:
Java 17, more specific the 'java.security'-library accepts keys which look alike the PKCS#1-format but are slightly different. They are using the SubjectPublicKeyInfo (or SPKI) specification.
The SPKI specification follows the RFC 5280.
- It is not possible to change the microservice.
- It is searched for a solution to generate a RSA key pair in swift (iOS) following the SPKI specification.
- Transformation from a PKCS#1-format is preferred.
- An external library (such as OpenSSL) may be used. Still, native swift code is in favor to prevent weakness in "security"-related functions.
Setup
- Swift in Xcode (IDE)
- Emulator for iPhone14
Sample Code: Generating a KeyPair (Swift - iOS)
// Keypair attributes
let tag = "my_personal_keystore_keypair_alias".data(using: .utf8)!
let attributes: [String: Any] =
[kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: "4096",
kSecPrivateKeyAttrs as String:
[kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag]
]
var error: Unmanaged<CFError>?
// Generate PrivateKey / Keypair
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
throw error!.takeRetainedValue() as Error
}
// Extract PublicKey
guard let publicKey = SecKeyCopyPublicKey(privateKey),
let publicKeyOptional = SecKeyCopyExternalRepresentation(publicKey, nil) else {
return "PublicKey could not be accessed."
}
let publicKeyData = publicKeyOptional as Data
let base64PublicKey = publicKeyData.base64EncodedString()
print("PublicKey, base64: ", base64PublicKey)
The given swift-code generates a RSA key pair in PKCS#1-format. Details on the key-formats may be retrieved from this question:
Problem
Still the wrong format (ÜKCS#1) is retrieved.
Not the objective
This section shall prevent typical mistakes along the research. The following mistakes can be excluded:
A) The key provided by iOS is BASE64 encoded - it has been handeled already .. :)
B) The code transforming the public key is in Objective-C. This till remains a legit alternative to the primary objective of this question .. ^.^
C) Swift/iOS hates Keys (KeyPairs) to be overwritten. If you need a new KeyPair, delete the old one using its ALIAS and thereafter create a new KeyPair. Already solved for this question .. :D
D) Other standards/formats are explicitly not included in the solution space although they may implicitly be containers for the desired SPKI-Format. To mention left outs: ASN.1, DER, PEM, x509, PKCS#1 etc. .. :)
- Especially PEM: https://developer.apple.com/forums/thread/85915
- https://www.cryptologie.net/article/260/asn1-vs-der-vs-pem-vs-x509-vs-pkcs7-vs/
E) Things & Links that may come into my mind later on .. ;-)
Sample Java code for testing
Sample keys can be found in the Appendix below.
Parsing the key(s) generated by Java 17:
public Optional<PublicKey> validateKeyFromJava(String publicKey) {
try {
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(EncryptionProperties.ALGORITHM);
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
return Optional.ofNullable(keyFactory.generatePublic(publicKeySpec));
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IllegalArgumentException | NullPointerException e) {
return Optional.empty();
}
}
The error to be overcome
The PKCS#1-format can not be read by the Java 17 microservice.
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException:
IOException: algid parse error, not a sequence
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:241)
at java.base/java.security.KeyFactory.generatePublic(KeyFactory.java:351)
Therefore the SPKI-format is needed to be used by Swift (iOS).
Hope
In case there is no solution using native Swift, the following approach using OpenSSL may be tried (not happened, yet).
Anyways
Thanks for reading & sharing - any help is appreciated :)
Appendix
All keys may be analyzed:
Multiple keys are given to prevent 'lucky shots' .. ;-)
Sample keys - Swift iOS (PKCS#1)
First:
MIICCgKCAgEAl0HYn9IdRmexAR9dSh3SxmFazWF0RV2TKmtRxGySvCA+aHZ/Dp+8tC0YDWpQzP+tZdlDWNOBj/D7i1z4b+UZk8F9ZEoi+w61kYQz+KjMkRuYrPBFi4A/gsS2qGeFJ4OvLQzGObZ0C+5/E+wunUWyQCVjgjTHKH8yqfVXeWYFKmaSSZblSZJAObE8Ao5J38DMINF1oWG+GdZt8RTLf35ULLEa8zKvFXrfBkDjiQH90WKPwDxWwvFInqZhjpsFxLytiKW+iBLqa4+0P7uwXVodFXa38RW9dk9mEsLvj6764BKtPAaWym9XZfEZNBu0jwlfO07k0augynGps6bsSIyYglDImlTRagdA/e+1AMBlSxEFVO4NpCjEpMT7rNX/LYPeEaJ8fTC3axOM1yEntcwUfSSCDulVPGlWlFbPxt29y1RrGtMmwfbTlbOQf2okMf0mGx9Ytd9HWadIdWh4FqDVWA8MF82PP1YsOW5TA0hkprK1qJwfkaLRKnmpfL5a7gWn4HWzpdDqrezhbc/zTCeHbX5c61mgWsAIWnB3fyXsJHpR62+QtBEznwhDxafVCQyUmsDqbncBxilEnFIn08G+6ox2PQC8GhNdpFVGsSoqpDfctsm51/tUYLpyeIBdzw/3nMLL1J5jL3yWr7ZKgnzNwjpC8l6c6gpsF3NRodeVhp8CAwEAAQ==
Second:
MIICCgKCAgEAlSbN7rlX6EMCDGuxQm9G6qqXIWshDvI5VaN4QPNCFcFzPjI/FyaHqi43+mxTyKGycT6TNqvanSu67yoIA80tSlFH2LndWv6sPQeHKxNwwFKU98Y/uL3M6hKIVXDwa6kZGM58dfY9qMWEOPXB4AwZtVaxJ4ePHFAR0kEOAHLCPpQxFkNlkg9FlCwlBzZbhHkI5uhCmlGEiLpLaJNJzjn7yo33m65189J6tIh3vopZ2ahFHb/vo6SVSbtS7Y0YlinJwH3MCGLm5+pKBpE64t5lgEhDPYSF7pKpLhEVqC5ETaya3mYTkXPSCiY/9Mo5zddniUGrxAJaY940jY3QNYeFmWPEEdhhIW2tUbuiM3IlHAqk4Du5p/2o1QcSVZdBsHStSGdcWqs00Z+ooxXwrOpMOUnZeb8Jt5dGDyHwjOmPf0N8dDQwz+5pgOoTkxd/z5cTK9tMv/nC+Mbbt8LRsct16M3LYrRAYnA8unX1ZD3eXTJPOSB/fM9Hmf1ObxQro9tatC5RaJjS0Xg5aepUsey62BW9lj4kHCkRPD4w1OmjDWGUCOSEhwy0KwqFyRBppYUMndEbJb3GKEjpekcQYwjERPtH/vEVxaN5gGYaCORancUaNH+d03zAmi0G830QXQvyohyKUkGw5qljEBH5R5Wqu7YLTlUes0rQEx8DpLVclaMCAwEAAQ==
Sample keys - Java 17 (SPKI-format)
First:
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqwMRLS3hhNuVBQTqRT4714fbl4h3PtrSZQ8Ry1qMCefFOLzmLmLD/VdnFoHj3QiqlZMlajvVuJonprhOy911aNW2Qs2VZ+zoMkLRjah9gqg00dLVtdWa2FXjAX6bh/rSR6jmF1hzfLPs/CqOKyDpX003AUF/WvgHkuAizQjZeskEDKawbExs6RSSFHNycrGwB9hBhAwGvyZpC2+fqPN/93W2NZ8xyb5H6CmM7pCpG+sTcsEEYOZjjq2HV8vYdM9KHi7O+nmY0MJxjLJ5JOv5oLqPXFt4Epezz4v2C3oE3Leu4gIy1r1D2xHuxu0pyQ9F2nI7a+6mGZbRAYDA8Yq2oidqBDC9pKogoHcMYhXj/G0WNEhE9ODuHg+GkiiGc3zysuKwfKu1Z5ZmUtlI1kVFqUEEi81smylTXtkU/oEf7P0OX94XcNTq1N3iO+nuFayAhINlvLUXwyO4JQUsmCyu0bH17XuNUfbnSCmOfGhFSjpyU0PthW9Qtf9yY9MmyZz9c9T2kfxoUxBnNRhVUZ+Kg8oA6kkNJp/ac+AdZzkPZFev91ZKYCbyI+rcakJ4KBQ5YoprDtpHmAQZ5E3/rWcq1Tis0yiomE2+natrzaO4aQbrljOHEgB6arbMkeu7/sZHEvYfK7ilH7tsZfDdU2DVOV0yxNReYwOHAFgFMTNQvBsCAwEAAQ==
Second:
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs9ywiZnmv9Ewf+dIsmwV8ZlZKQNg4lbVLpNptb3pftnoukvBjak1rDqb6GcxXtM+UuBgr4Wigi0TI+vItzWv6QlBB8HShA4WImKrOCD3+U1fFdDpwCxQO+oHqTqeNKhRcKcM0e0C/c88hJo8l9G2OCjIANW3O+pGeMirB/XjPdcQ+d37TFGpRs83wPR8gUFQsH8qQMkS7uOtTCZHfcK6UzbvJB3Gf/llcCSfPYKUMY9SXIc5K9hpI0E1v5EdEUvdbhiilZI0esntr5BzeO5AxH/m9fFPH9ekZZyc9nXsHY7tPOJMD+wsTad4D9NBGi9x+lzxZRdxyDLote4ix+aHSqMgcdtOyJ69WFym2Ty1VfCgrmG8fhC/PZBEzk6obK5uJD4mO3owrKgYsmJgZHO3CbVkmv04+EEPpQLippQu8uCl+2KO480EvjSco5ryVH3XEsAGokBLCsZviBtntY/Ia0OLXPmy7WWXigxsVQkgPZ1SyZa3FUp/Zuwtoo0BWDI/9JdUZPfKhbQkcxtnKbCe8QXf51YUgIfKXPTBlmk/Zj931EzXdQCZFMvgK+I5p79DqCsD9yKbiUnfK9tXJ4SzMfuiLd4pqB0UIMVMQEj5SZPYn7eHRZyje4v96FDwtj56NQ/kZPYXKqLoOv5nvMALZngzJ6aFaGjkWZX9RNQLfA8CAwEAAQ==