Skip to content
This repository was archived by the owner on Apr 13, 2026. It is now read-only.

Commit fb06bdb

Browse files
committed
Use EC signature configuration
MOPPIOS-1493 Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent c626688 commit fb06bdb

File tree

6 files changed

+67
-59
lines changed

6 files changed

+67
-59
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ xcuserdata
3434
MoppApp/GoogleService-Info.plist
3535
MoppApp/MoppApp/config.json
3636
MoppApp/MoppApp/defaultConfiguration.json
37-
MoppApp/MoppApp/publicKey.pub
38-
MoppApp/MoppApp/signature.rsa
37+
MoppApp/MoppApp/publicKey.ecpub
38+
MoppApp/MoppApp/signature.ecc

MoppApp/MoppApp.xcodeproj/project.pbxproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@
248248
DFF3C3B22332314A0079458A /* RuntimeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFF3C3B02332314A0079458A /* RuntimeError.swift */; };
249249
DFF3C3B32332314A0079458A /* SignatureVerifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFF3C3B12332314A0079458A /* SignatureVerifier.swift */; };
250250
DFF3C3B5233231F20079458A /* Notification+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFF3C3B4233231F20079458A /* Notification+Additions.swift */; };
251-
DFF3C3BC2332355D0079458A /* publicKey.pub in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3B82332355C0079458A /* publicKey.pub */; };
251+
DFF3C3BC2332355D0079458A /* publicKey.ecpub in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3B82332355C0079458A /* publicKey.ecpub */; };
252252
DFF3C3BD2332355D0079458A /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3B92332355C0079458A /* config.json */; };
253-
DFF3C3BE2332355D0079458A /* signature.rsa in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3BA2332355C0079458A /* signature.rsa */; };
253+
DFF3C3BE2332355D0079458A /* signature.ecc in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3BA2332355C0079458A /* signature.ecc */; };
254254
DFF3C3BF2332355D0079458A /* defaultConfiguration.json in Resources */ = {isa = PBXBuildFile; fileRef = DFF3C3BB2332355D0079458A /* defaultConfiguration.json */; };
255255
E4250CCB1E0968D200530370 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4250CCA1E0968D200530370 /* AppDelegate.swift */; };
256256
E4250D0A1E0AA7AF00530370 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E4250D091E0AA7AF00530370 /* LaunchScreen.xib */; };
@@ -570,9 +570,9 @@
570570
DFF3C3B02332314A0079458A /* RuntimeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuntimeError.swift; sourceTree = "<group>"; };
571571
DFF3C3B12332314A0079458A /* SignatureVerifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignatureVerifier.swift; sourceTree = "<group>"; };
572572
DFF3C3B4233231F20079458A /* Notification+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+Additions.swift"; sourceTree = "<group>"; };
573-
DFF3C3B82332355C0079458A /* publicKey.pub */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = publicKey.pub; path = MoppApp/publicKey.pub; sourceTree = "<group>"; };
573+
DFF3C3B82332355C0079458A /* publicKey.ecpub */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = publicKey.ecpub; path = MoppApp/publicKey.ecpub; sourceTree = "<group>"; };
574574
DFF3C3B92332355C0079458A /* config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = config.json; path = MoppApp/config.json; sourceTree = "<group>"; };
575-
DFF3C3BA2332355C0079458A /* signature.rsa */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = signature.rsa; path = MoppApp/signature.rsa; sourceTree = "<group>"; };
575+
DFF3C3BA2332355C0079458A /* signature.ecc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = signature.ecc; path = MoppApp/signature.ecc; sourceTree = "<group>"; };
576576
DFF3C3BB2332355D0079458A /* defaultConfiguration.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = defaultConfiguration.json; path = MoppApp/defaultConfiguration.json; sourceTree = "<group>"; };
577577
DFF6A55627E14D3B0055F8D5 /* RoleDetailsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoleDetailsViewControllerTests.swift; sourceTree = "<group>"; };
578578
E4250CC31E0968D200530370 /* MoppApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MoppApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1048,8 +1048,8 @@
10481048
DFB1D5EA2ACAFE1B00FDC7B8 /* GoogleService-Info.plist */,
10491049
DFF3C3B92332355C0079458A /* config.json */,
10501050
DFF3C3BB2332355D0079458A /* defaultConfiguration.json */,
1051-
DFF3C3B82332355C0079458A /* publicKey.pub */,
1052-
DFF3C3BA2332355C0079458A /* signature.rsa */,
1051+
DFF3C3B82332355C0079458A /* publicKey.ecpub */,
1052+
DFF3C3BA2332355C0079458A /* signature.ecc */,
10531053
E4250CC51E0968D200530370 /* MoppApp */,
10541054
54A418251E83FAD200559E2B /* shareExtension */,
10551055
DFF6A54E27E14C180055F8D5 /* MoppAppTests */,
@@ -1378,8 +1378,8 @@
13781378
DFB1D5EB2ACAFE1B00FDC7B8 /* GoogleService-Info.plist in Resources */,
13791379
DFF3C3BF2332355D0079458A /* defaultConfiguration.json in Resources */,
13801380
DFF3C3BD2332355D0079458A /* config.json in Resources */,
1381-
DFF3C3BE2332355D0079458A /* signature.rsa in Resources */,
1382-
DFF3C3BC2332355D0079458A /* publicKey.pub in Resources */,
1381+
DFF3C3BE2332355D0079458A /* signature.ecc in Resources */,
1382+
DFF3C3BC2332355D0079458A /* publicKey.ecpub in Resources */,
13831383
DF900C972386768F00887385 /* tslFiles.bundle in Resources */,
13841384
DFC2ADC329437790008A1CD2 /* Accessibility.storyboard in Resources */,
13851385
C50DCD011FC6E97400D48E16 /* Container.storyboard in Resources */,

MoppApp/MoppApp/SettingsConfiguration.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegat
102102
internal func loadLocalConfiguration() {
103103
do {
104104
let localConfigData = try String(contentsOfFile: Bundle.main.path(forResource: "config", ofType: "json")!)
105-
let localSignature = try String(contentsOfFile: Bundle.main.path(forResource: "signature", ofType: "rsa")!)
105+
let localSignature = try String(contentsOfFile: Bundle.main.path(forResource: "signature", ofType: "ecc")!)
106106
let decodedData = try MOPPConfiguration(json: localConfigData)
107107
setAllConfigurationToCache(configData: localConfigData, signature: localSignature, initialUpdateDate: MoppDateFormatter().stringToDate(dateString: getDefaultMoppConfiguration().UPDATEDATE), versionSerial: decodedData.METAINF.SERIAL)
108108
setConfigurationToCache("", forKey: "lastUpdateDateCheck")
@@ -119,7 +119,7 @@ class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegat
119119
internal func loadCachedConfiguration() {
120120
do {
121121
let cachedConfigData = getConfigurationFromCache(forKey: "config") as! String
122-
let localPublicKey = try String(contentsOfFile: Bundle.main.path(forResource: "publicKey", ofType: "pub")!)
122+
let localPublicKey = try String(contentsOfFile: Bundle.main.path(forResource: "publicKey", ofType: "ecpub")!)
123123
let cachedSignature = getConfigurationFromCache(forKey: "signature") as! String
124124

125125
_ = try SignatureVerifier.isSignatureCorrect(configData: cachedConfigData, publicKey: localPublicKey, signature: cachedSignature)
@@ -152,14 +152,14 @@ class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegat
152152
internal func loadCentralConfiguration(completionHandler: @escaping (Error) -> () = { _ in }) {
153153
do {
154154
let cachedSignature = getConfigurationFromCache(forKey: "signature") as? String
155-
let localPublicKey = try String(contentsOfFile: Bundle.main.path(forResource: "publicKey", ofType: "pub")!)
156-
155+
let localPublicKey = try String(contentsOfFile: Bundle.main.path(forResource: "publicKey", ofType: "ecpub")!)
156+
157157
if isInitialSetup() {
158158
setConfigurationToCache(true, forKey: "isCentralConfigurationLoaded")
159159
loadCachedConfiguration()
160160
}
161161

162-
getFetchedData(fromUrl: "\(getDefaultMoppConfiguration().CENTRALCONFIGURATIONSERVICEURL)/config.rsa") { (centralSignature, signatureError) in
162+
getFetchedData(fromUrl: "\(getDefaultMoppConfiguration().CENTRALCONFIGURATIONSERVICEURL)/config.ecc") { (centralSignature, signatureError) in
163163
if let error = signatureError {
164164
printLog(error.localizedDescription)
165165
return completionHandler(error)

MoppApp/MoppApp/SignatureVerifier.swift

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*
2222
*/
2323

24-
import Security
24+
import CryptoKit
2525

2626
class SignatureVerifier {
2727

@@ -30,24 +30,28 @@ class SignatureVerifier {
3030
throw Exception("Invalid signature")
3131
}
3232
guard let pubKey = fromBase64(publicKey
33-
.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
34-
.replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: "")) else {
33+
.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
34+
.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")) else {
3535
throw Exception("Invalid public key")
3636
}
37-
let parameters: [CFString: Any] = [
38-
kSecAttrKeyType: kSecAttrKeyTypeRSA,
39-
kSecAttrKeyClass: kSecAttrKeyClassPublic,
40-
kSecReturnPersistentRef: false
41-
]
42-
var error: Unmanaged<CFError>?
43-
guard let key = SecKeyCreateWithData(pubKey as CFData, parameters as CFDictionary, &error) else {
44-
printLog("Failed to create key: \(error!.takeRetainedValue())")
45-
throw Exception("Failed to create key: \(error!.takeRetainedValue())")
37+
let result: Bool
38+
switch pubKey.count {
39+
case 91:
40+
let key = try P256.Signing.PublicKey(derRepresentation: pubKey)
41+
let sig = try P256.Signing.ECDSASignature(derRepresentation: sigData)
42+
result = key.isValidSignature(sig, for: Data(configData.utf8))
43+
case 120:
44+
let key = try P384.Signing.PublicKey(derRepresentation: pubKey)
45+
let sig = try P384.Signing.ECDSASignature(derRepresentation: sigData)
46+
result = key.isValidSignature(sig, for: Data(configData.utf8))
47+
case 158:
48+
let key = try P521.Signing.PublicKey(derRepresentation: pubKey)
49+
let sig = try P521.Signing.ECDSASignature(derRepresentation: sigData)
50+
result = key.isValidSignature(sig, for: Data(configData.utf8))
51+
default:
52+
throw Exception("Unknown key size")
4653
}
47-
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA512
48-
let result = SecKeyVerifySignature(key, algorithm, Data(configData.utf8) as CFData, sigData as CFData, &error)
4954
if !result {
50-
print("Verification error: \(error!.takeRetainedValue())")
5155
throw Exception("Signature verification unsuccessful")
5256
}
5357
}
Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
// swift-tools-version:4.2
22
import PackageDescription
33

4-
let package = Package(name: "SetupConfiguration")
5-
6-
package.products = [
7-
.executable(name: "SetupConfiguration", targets: ["SetupConfiguration"])
8-
]
9-
package.dependencies = [
10-
11-
]
12-
package.targets = [
13-
.target(name: "SetupConfiguration", dependencies: [], path: "Sources")
14-
]
4+
let package = Package(
5+
name: "SetupConfiguration",
6+
platforms: [.macOS(.v11)],
7+
products: [.executable(name: "SetupConfiguration", targets: ["SetupConfiguration"])],
8+
dependencies: [],
9+
targets: [.target(name: "SetupConfiguration", dependencies: [], path: "Sources")],
10+
)

MoppApp/SetupConfiguration/Sources/main.swift

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/swift sh
22

33
import Foundation
4-
import Security
4+
import CryptoKit
55

66
// MARK: - Settings Configuration
77

@@ -26,8 +26,8 @@ class SettingsConfiguration {
2626

2727
log("1 / 4 - Downloading configuration data...")
2828
let configData = try fetchData(from: "\(configBaseUrl)/config.json")
29-
let publicKey = try fetchData(from: "\(configBaseUrl)/config.pub")
30-
let signature = try fetchData(from: "\(configBaseUrl)/config.rsa")
29+
let publicKey = try fetchData(from: "\(configBaseUrl)/config.ecpub")
30+
let signature = try fetchData(from: "\(configBaseUrl)/config.ecc")
3131

3232
log("2 / 4 - Verifying signature...")
3333
try verifySignature(configData: configData, publicKey: publicKey, signature: signature)
@@ -38,8 +38,8 @@ class SettingsConfiguration {
3838

3939
log("4 / 4 - Saving and moving files...")
4040
try saveFile(named: "config.json", content: configData)
41-
try saveFile(named: "publicKey.pub", content: publicKey)
42-
try saveFile(named: "signature.rsa", content: signature)
41+
try saveFile(named: "publicKey.ecpub", content: publicKey)
42+
try saveFile(named: "signature.ecc", content: signature)
4343
try saveFile(named: "defaultConfiguration.json", content: defaultConfiguration)
4444

4545
log("Default configuration initialized successfully!")
@@ -64,27 +64,35 @@ extension SettingsConfiguration {
6464
throw ConfigurationError.signatureVerificationFailed
6565
}
6666
guard let pubKey = Data(base64Encoded: publicKey
67-
.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
68-
.replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: ""), options: .ignoreUnknownCharacters) else {
67+
.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
68+
.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: ""), options: .ignoreUnknownCharacters) else {
69+
log("Failed to parse key")
6970
throw ConfigurationError.signatureVerificationFailed
7071
}
7172
guard let sigData = Data(base64Encoded: signature, options: .ignoreUnknownCharacters) else {
7273
throw ConfigurationError.signatureVerificationFailed
7374
}
74-
let parameters: [CFString: Any] = [
75-
kSecAttrKeyType: kSecAttrKeyTypeRSA,
76-
kSecAttrKeyClass: kSecAttrKeyClassPublic,
77-
kSecReturnPersistentRef: false
78-
]
79-
var error: Unmanaged<CFError>?
80-
guard let key = SecKeyCreateWithData(pubKey as CFData, parameters as CFDictionary, &error) else {
81-
log("Key importing failed \(error?.takeRetainedValue().localizedDescription ?? "")")
75+
76+
let result: Bool
77+
switch pubKey.count {
78+
case 91:
79+
let key = try P256.Signing.PublicKey(derRepresentation: pubKey)
80+
let sig = try P256.Signing.ECDSASignature(derRepresentation: sigData)
81+
result = key.isValidSignature(sig, for: Data(configData.utf8))
82+
case 120:
83+
let key = try P384.Signing.PublicKey(derRepresentation: pubKey)
84+
let sig = try P384.Signing.ECDSASignature(derRepresentation: sigData)
85+
result = key.isValidSignature(sig, for: Data(configData.utf8))
86+
case 158:
87+
let key = try P521.Signing.PublicKey(derRepresentation: pubKey)
88+
let sig = try P521.Signing.ECDSASignature(derRepresentation: sigData)
89+
result = key.isValidSignature(sig, for: Data(configData.utf8))
90+
default:
91+
log("Unknown key size")
8292
throw ConfigurationError.signatureVerificationFailed
8393
}
84-
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA512
85-
let result = SecKeyVerifySignature(key, algorithm, Data(configData.utf8) as CFData, sigData as CFData, &error)
8694
if !result {
87-
log("Signature verifying failed \(error?.takeRetainedValue().localizedDescription ?? "")")
95+
log("Signature verifying failed")
8896
throw ConfigurationError.signatureVerificationFailed
8997
}
9098
log("Signature verified successfully!")

0 commit comments

Comments
 (0)