@@ -56,21 +56,14 @@ enum CredentialPublicKey: Sendable {
56
56
return
57
57
}
58
58
59
- guard let keyTypeRaw = publicKeyObject [ COSEKey . kty. cbor] ,
60
- case let . unsignedInt( keyTypeInt) = keyTypeRaw,
61
- let keyType = COSEKeyType ( rawValue: keyTypeInt) else {
62
- throw WebAuthnError . invalidKeyType
63
- }
59
+ guard let keyType = publicKeyObject [ COSEKey . kty] . flatMap ( UInt64 . init) . flatMap ( COSEKeyType . init ( rawValue: ) )
60
+ else { throw WebAuthnError . invalidKeyType }
64
61
65
- guard let algorithmRaw = publicKeyObject [ COSEKey . alg. cbor] ,
66
- case let . negativeInt( algorithmNegative) = algorithmRaw else {
67
- throw WebAuthnError . invalidAlgorithm
68
- }
69
- // https://github.com/unrelentingtech/SwiftCBOR#swiftcbor
70
- // Negative integers are decoded as NegativeInt(UInt), where the actual number is -1 - i
71
- guard let algorithm = COSEAlgorithmIdentifier ( rawValue: - 1 - Int( algorithmNegative) ) else {
72
- throw WebAuthnError . unsupportedCOSEAlgorithm
73
- }
62
+ guard let algorithmRaw = publicKeyObject [ COSEKey . alg] . flatMap ( Int . init)
63
+ else { throw WebAuthnError . invalidAlgorithm }
64
+
65
+ guard let algorithm = COSEAlgorithmIdentifier ( rawValue: algorithmRaw)
66
+ else { throw WebAuthnError . unsupportedCOSEAlgorithm }
74
67
75
68
// Currently we only support elliptic curve algorithms
76
69
switch keyType {
@@ -89,6 +82,14 @@ enum CredentialPublicKey: Sendable {
89
82
func verify( signature: some DataProtocol , data: some DataProtocol ) throws {
90
83
try key. verify ( signature: signature, data: data)
91
84
}
85
+
86
+ var bytes : [ UInt8 ] {
87
+ switch self {
88
+ case . okp( let oKPPublicKey) : oKPPublicKey. bytes
89
+ case . ec2( let eC2PublicKey) : eC2PublicKey. bytes
90
+ case . rsa( let rSAPublicKeyData) : rSAPublicKeyData. bytes
91
+ }
92
+ }
92
93
}
93
94
94
95
struct EC2PublicKey : PublicKey , Sendable {
@@ -108,31 +109,72 @@ struct EC2PublicKey: PublicKey, Sendable {
108
109
self . xCoordinate = xCoordinate
109
110
self . yCoordinate = yCoordinate
110
111
}
112
+
113
+ init ( _ publicKey: P256 . Signing . PublicKey ) {
114
+ self . algorithm = . algES256
115
+ self . curve = . p256
116
+
117
+ /// Split the key like SwiftCrypto does internally: https://github.com/apple/swift-crypto/blob/606608da0875e3dee07cb37da3b38585420db111/Sources/Crypto/Signatures/ECDSA.swift.gyb#L79
118
+ let rawRepresentation = publicKey. rawRepresentation
119
+ let half = rawRepresentation. count/ 2
120
+ self . xCoordinate = Array ( rawRepresentation. prefix ( half) )
121
+ self . yCoordinate = Array ( rawRepresentation. suffix ( half) )
122
+ }
123
+
124
+ init ( _ publicKey: P384 . Signing . PublicKey ) {
125
+ self . algorithm = . algES384
126
+ self . curve = . p384
127
+
128
+ /// Split the key like SwiftCrypto does internally: https://github.com/apple/swift-crypto/blob/606608da0875e3dee07cb37da3b38585420db111/Sources/Crypto/Signatures/ECDSA.swift.gyb#L79
129
+ let rawRepresentation = publicKey. rawRepresentation
130
+ let half = rawRepresentation. count/ 2
131
+ self . xCoordinate = Array ( rawRepresentation. prefix ( half) )
132
+ self . yCoordinate = Array ( rawRepresentation. suffix ( half) )
133
+ }
134
+
135
+ init ( _ publicKey: P521 . Signing . PublicKey ) {
136
+ self . algorithm = . algES512
137
+ self . curve = . p521
138
+
139
+ /// Split the key like SwiftCrypto does internally: https://github.com/apple/swift-crypto/blob/606608da0875e3dee07cb37da3b38585420db111/Sources/Crypto/Signatures/ECDSA.swift.gyb#L79
140
+ let rawRepresentation = publicKey. rawRepresentation
141
+ let half = rawRepresentation. count/ 2
142
+ self . xCoordinate = Array ( rawRepresentation. prefix ( half) )
143
+ self . yCoordinate = Array ( rawRepresentation. suffix ( half) )
144
+ }
111
145
112
146
init ( publicKeyObject: CBOR , algorithm: COSEAlgorithmIdentifier ) throws {
113
147
self . algorithm = algorithm
114
148
115
149
// Curve is key -1 - or -0 for SwiftCBOR
116
150
// X Coordinate is key -2, or NegativeInt 1 for SwiftCBOR
117
151
// Y Coordinate is key -3, or NegativeInt 2 for SwiftCBOR
118
- guard let curveRaw = publicKeyObject [ COSEKey . crv. cbor] ,
119
- case let . unsignedInt( curve) = curveRaw,
120
- let coseCurve = COSECurve ( rawValue: curve) else {
121
- throw WebAuthnError . invalidCurve
122
- }
152
+ guard let coseCurve = publicKeyObject [ COSEKey . crv] . flatMap ( UInt64 . init) . flatMap ( COSECurve . init ( rawValue: ) )
153
+ else { throw WebAuthnError . invalidCurve }
123
154
self . curve = coseCurve
124
155
125
- guard let xCoordRaw = publicKeyObject [ COSEKey . x . cbor ] ,
126
- case let . byteString ( xCoordinateBytes ) = xCoordRaw else {
127
- throw WebAuthnError . invalidXCoordinate
128
- }
156
+ guard
157
+ let xCoordRaw = publicKeyObject [ COSEKey . x ] ,
158
+ case let . byteString ( xCoordinateBytes ) = xCoordRaw
159
+ else { throw WebAuthnError . invalidXCoordinate }
129
160
xCoordinate = xCoordinateBytes
130
- guard let yCoordRaw = publicKeyObject [ COSEKey . y. cbor] ,
131
- case let . byteString( yCoordinateBytes) = yCoordRaw else {
132
- throw WebAuthnError . invalidYCoordinate
133
- }
161
+
162
+ guard
163
+ let yCoordRaw = publicKeyObject [ COSEKey . y] ,
164
+ case let . byteString( yCoordinateBytes) = yCoordRaw
165
+ else { throw WebAuthnError . invalidYCoordinate }
134
166
yCoordinate = yCoordinateBytes
135
167
}
168
+
169
+ var bytes : [ UInt8 ] {
170
+ CBOR . encodeSortedPairs ( [
171
+ ( COSEKey . kty, . signedInt( COSEKeyType . ellipticKey) ) ,
172
+ ( COSEKey . alg, . signedInt( algorithm) ) ,
173
+ ( COSEKey . crv, . signedInt( curve) ) ,
174
+ ( COSEKey . x, . byteString( Array ( xCoordinate) ) ) ,
175
+ ( COSEKey . y, . byteString( Array ( yCoordinate) ) ) ,
176
+ ] )
177
+ }
136
178
137
179
func verify( signature: some DataProtocol , data: some DataProtocol ) throws {
138
180
switch algorithm {
@@ -171,18 +213,27 @@ struct RSAPublicKeyData: PublicKey, Sendable {
171
213
init ( publicKeyObject: CBOR , algorithm: COSEAlgorithmIdentifier ) throws {
172
214
self . algorithm = algorithm
173
215
174
- guard let nRaw = publicKeyObject [ COSEKey . n . cbor ] ,
175
- case let . byteString ( nBytes ) = nRaw else {
176
- throw WebAuthnError . invalidModulus
177
- }
216
+ guard
217
+ let nRaw = publicKeyObject [ COSEKey . n ] ,
218
+ case let . byteString ( nBytes ) = nRaw
219
+ else { throw WebAuthnError . invalidModulus }
178
220
n = nBytes
179
221
180
- guard let eRaw = publicKeyObject [ COSEKey . e . cbor ] ,
181
- case let . byteString ( eBytes ) = eRaw else {
182
- throw WebAuthnError . invalidExponent
183
- }
222
+ guard
223
+ let eRaw = publicKeyObject [ COSEKey . e ] ,
224
+ case let . byteString ( eBytes ) = eRaw
225
+ else { throw WebAuthnError . invalidExponent }
184
226
e = eBytes
185
227
}
228
+
229
+ var bytes : [ UInt8 ] {
230
+ CBOR . encodeSortedPairs ( [
231
+ ( COSEKey . kty, . signedInt( COSEKeyType . rsaKey) ) ,
232
+ ( COSEKey . alg, . signedInt( algorithm) ) ,
233
+ ( COSEKey . n, . byteString( Array ( n) ) ) ,
234
+ ( COSEKey . e, . byteString( Array ( e) ) ) ,
235
+ ] )
236
+ }
186
237
187
238
func verify( signature: some DataProtocol , data: some DataProtocol ) throws {
188
239
throw WebAuthnError . unsupported
@@ -228,6 +279,15 @@ struct OKPPublicKey: PublicKey, Sendable {
228
279
}
229
280
xCoordinate = xCoordinateBytes
230
281
}
282
+
283
+ var bytes : [ UInt8 ] {
284
+ CBOR . encodeSortedPairs ( [
285
+ ( COSEKey . kty, . signedInt( COSEKeyType . octetKey) ) ,
286
+ ( COSEKey . alg, . signedInt( algorithm) ) ,
287
+ ( COSEKey . crv, . unsignedInt( curve) ) ,
288
+ ( COSEKey . x, . byteString( xCoordinate) ) ,
289
+ ] )
290
+ }
231
291
232
292
func verify( signature: some DataProtocol , data: some DataProtocol ) throws {
233
293
throw WebAuthnError . unsupported
0 commit comments