-
-
Notifications
You must be signed in to change notification settings - Fork 62
Add PEM representation init and property to EdDSA keys #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,6 @@ import JWTKit | |
|
|
||
| @Suite("EdDSA Tests") | ||
| struct EdDSATests { | ||
|
|
||
| @Test("Test EdDSA Generate") | ||
| func edDSAGenerate() async throws { | ||
| let payload = TestPayload( | ||
|
|
@@ -24,9 +23,10 @@ struct EdDSATests { | |
|
|
||
| @Test("Test EdDSA Public and Private") | ||
| func edDSAPublicPrivate() async throws { | ||
| let keys = try await JWTKeyCollection() | ||
| .add(eddsa: EdDSA.PublicKey(x: eddsaPublicKeyBase64, curve: .ed25519), kid: "public") | ||
| .add(eddsa: EdDSA.PrivateKey(d: eddsaPrivateKeyBase64, curve: .ed25519), kid: "private") | ||
| let signingCollection = try await JWTKeyCollection() | ||
| .add(eddsa: EdDSA.PrivateKey(d: eddsaPrivateKeyBase64, curve: .ed25519)) | ||
| let verifyingCollection = try await JWTKeyCollection() | ||
| .add(eddsa: EdDSA.PublicKey(x: eddsaPublicKeyBase64, curve: .ed25519)) | ||
|
Comment on lines
-27
to
+29
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why have these tests changed?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because before it seemed like it was using the public key to verify but it wasn't. It wasn't wrong per se but a bit misleading |
||
|
|
||
| let payload = TestPayload( | ||
| sub: "vapor", | ||
|
|
@@ -35,21 +35,14 @@ struct EdDSATests { | |
| exp: .init(value: .init(timeIntervalSince1970: 2_000_000_000)) | ||
| ) | ||
|
|
||
| for _ in 0..<1000 { | ||
| let token = try await keys.sign(payload, kid: "private") | ||
| // test public signer decoding | ||
| let verifiedPayload = try await keys.verify(token, as: TestPayload.self) | ||
| #expect(verifiedPayload == payload) | ||
| } | ||
| let token = try await signingCollection.sign(payload, kid: "private") | ||
| // test public signer decoding | ||
| let verifiedPayload = try await verifyingCollection.verify(token, as: TestPayload.self) | ||
| #expect(verifiedPayload == payload) | ||
| } | ||
|
|
||
| @Test("Test Verifying EdDSA Key Using JWK") | ||
| func verifyingEdDSAKeyUsingJWK() async throws { | ||
| struct Foo: JWTPayload { | ||
| var bar: Int | ||
| func verify(using _: some JWTAlgorithm) throws {} | ||
| } | ||
|
|
||
| // ecdsa key in base64 format | ||
| let x = eddsaPublicKeyBase64 | ||
| let d = eddsaPrivateKeyBase64 | ||
|
|
@@ -83,11 +76,6 @@ struct EdDSATests { | |
|
|
||
| @Test("Test Verifying EdDSA Key Using JWK Base64URL") | ||
| func verifyingEdDSAKeyUsingJWKBase64URL() async throws { | ||
| struct Foo: JWTPayload { | ||
| var bar: Int | ||
| func verify(using _: some JWTAlgorithm) throws {} | ||
| } | ||
|
|
||
| let x = eddsaPublicKeyBase64Url | ||
| let d = eddsaPrivateKeyBase64Url | ||
|
|
||
|
|
@@ -120,11 +108,6 @@ struct EdDSATests { | |
|
|
||
| @Test("Test Verifying EdDSA Key Using JWK with Mixed Base64 Formats") | ||
| func verifyingEdDSAKeyUsingJWKWithMixedBase64Formats() async throws { | ||
| struct Foo: JWTPayload { | ||
| var bar: Int | ||
| func verify(using _: some JWTAlgorithm) throws {} | ||
| } | ||
|
|
||
| // eddsa key in base64url format | ||
| let x = eddsaPublicKeyBase64Url | ||
| let d = eddsaPrivateKeyBase64 | ||
|
|
@@ -155,10 +138,51 @@ struct EdDSATests { | |
| let foo = try await keyCollection.verify(jwt, as: Foo.self) | ||
| #expect(foo.bar == 42) | ||
| } | ||
|
|
||
| @Test("Signing and Verifying with PEM") | ||
| func signingAndVerifyingWithPEM() async throws { | ||
| let signingKeyCollection = try await JWTKeyCollection() | ||
| .add(eddsa: EdDSA.PrivateKey(pem: eddsaPrivateKeyPEM)) | ||
|
|
||
| let verificationKeyCollection = try await JWTKeyCollection() | ||
| .add(eddsa: EdDSA.PublicKey(pem: eddsaPublicKeyPEM)) | ||
|
|
||
| let jwt = try await signingKeyCollection.sign(Foo(bar: 42)) | ||
| let foo = try await verificationKeyCollection.verify(jwt, as: Foo.self) | ||
| #expect(foo.bar == 42) | ||
| } | ||
|
|
||
| @Test("PEM representation") | ||
| func pemRepresentation() async throws { | ||
| let privateKey = try EdDSA.PrivateKey(pem: eddsaPrivateKeyPEM) | ||
| let derivedPrivateKey = try EdDSA.PrivateKey(pem: privateKey.pemRepresentation) | ||
| #expect(privateKey == derivedPrivateKey) | ||
|
|
||
| let publicKey = try EdDSA.PublicKey(pem: eddsaPublicKeyPEM) | ||
| let derivedPublicKey = try EdDSA.PublicKey(pem: publicKey.pemRepresentation) | ||
| #expect(publicKey == derivedPublicKey) | ||
| } | ||
|
|
||
| struct Foo: JWTPayload { | ||
| var bar: Int | ||
| func verify(using _: some JWTAlgorithm) throws {} | ||
| } | ||
| } | ||
|
|
||
| let eddsaPublicKeyBase64 = "0ZcEvMCSYqSwR8XIkxOoaYjRQSAO8frTMSCpNbUl4lE=" | ||
| let eddsaPrivateKeyBase64 = "d1H3/dcg0V3XyAuZW2TE5Z3rhY20M+4YAfYu/HUQd8w=" | ||
| let eddsaPublicKeyBase64Url = "0ZcEvMCSYqSwR8XIkxOoaYjRQSAO8frTMSCpNbUl4lE" | ||
| let eddsaPrivateKeyBase64Url = "d1H3_dcg0V3XyAuZW2TE5Z3rhY20M-4YAfYu_HUQd8w" | ||
|
|
||
| let eddsaPrivateKeyPEM = """ | ||
| -----BEGIN PRIVATE KEY----- | ||
| MC4CAQAwBQYDK2VwBCIEIJXTkfKlQbhHjAcfEjQH9BMqUAxXalmgl1zi5q9zgSXB | ||
| -----END PRIVATE KEY----- | ||
| """ | ||
|
|
||
| let eddsaPublicKeyPEM = """ | ||
| -----BEGIN PUBLIC KEY----- | ||
| MCowBQYDK2VwAyEAHprHxN90GB+Kue+eXMpwuJc1xcouR1V3ZpVFLrsdgUQ= | ||
| -----END PUBLIC KEY----- | ||
| """ | ||
| #endif // canImport(Testing) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why can't we also make them Hashable?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could if there's a use case for it. I wouldn't have made them
Equatableeither ifEquatableThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is generally useful to make all your types
Hashable, if they are. We can't foresee every usecase, but if someone wants to put them in aSet… there you go.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all keys should conform to
Hashablebecause… they areThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Equatablemeans "represents a value which can be meaningfully compared for sameness with another value".Identifiablemeans "represents a value which has unique identity even if it compares the same with another value".Hashablemeans "isEquatableand represents a value which can be quickly and efficiently reduced to a hashing key with appropriate properties".There are very few things which are semantically
Equatablewithout being semanticallyHashable. In Swift, "notHashable" is effectively used to mean "this type should not be treated as having sufficiently unique representation to be used as a dictionary key or to be uniqued by set inclusion".As regards asymmetric encryption keys,
Hashableis by this definition not semantically appropriate. You should not be keying a dictionary by a crypto key or trying to construct unique sets of crypto keys. In the infosec world, these would definitely qualify as potentially dangerous behaviors (in terms of reducing security).