Skip to content

Commit 8729e0b

Browse files
committed
Extract inner classes
1 parent 40e4197 commit 8729e0b

File tree

5 files changed

+198
-113
lines changed

5 files changed

+198
-113
lines changed

vertx-auth-common/src/main/java/io/vertx/ext/auth/impl/jose/JWK.java

Lines changed: 4 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838

3939
import static io.vertx.ext.auth.impl.Codec.base64MimeDecode;
4040
import static io.vertx.ext.auth.impl.Codec.base64UrlDecode;
41-
import static io.vertx.ext.auth.impl.jose.JWS.getSignatureLength;
4241

4342
/**
4443
* JWK https://tools.ietf.org/html/rfc7517
@@ -132,7 +131,7 @@ private static boolean invalidAlgAlias(String alg, String alias) {
132131
private final String label;
133132

134133
// the cryptography objects, not all will be initialized
135-
private SigningAlgorithm signingAlgorithm;
134+
private final SigningAlgorithm signingAlgorithm;
136135

137136
public static List<JWK> load(KeyStore keyStore, String keyStorePassword, Map<String, String> passwordProtection) {
138137
final List<JWK> keys = new ArrayList<>();
@@ -338,108 +337,6 @@ private static SigningAlgorithm parsePEM(String alg, String kty, KeyFactory kf,
338337
}
339338
}
340339

341-
static class MacSigningAlgorithm implements SigningAlgorithm {
342-
private final String name;
343-
private final Mac mac;
344-
public MacSigningAlgorithm(String name, Mac mac) {
345-
this.name = name;
346-
this.mac = mac;
347-
}
348-
@Override
349-
public String name() {
350-
return name;
351-
}
352-
@Override
353-
public Signer signer() {
354-
return new Signer() {
355-
@Override
356-
public byte[] sign(byte[] data) {
357-
synchronized (MacSigningAlgorithm.this) {
358-
return mac.doFinal(data);
359-
}
360-
}
361-
@Override
362-
public synchronized boolean verify(byte[] expected, byte[] payload) {
363-
synchronized (MacSigningAlgorithm.this) {
364-
return MessageDigest.isEqual(expected, sign(payload));
365-
}
366-
}
367-
};
368-
}
369-
}
370-
371-
static class PubKeySigningAlgorithm implements SigningAlgorithm {
372-
373-
private final String kty;
374-
private final String alg;
375-
private final PrivateKey privateKey;
376-
private final PublicKey publicKey;
377-
378-
public PubKeySigningAlgorithm(String kty, String alg, PrivateKey privateKey, PublicKey publicKey) {
379-
this.privateKey = privateKey;
380-
this.publicKey = publicKey;
381-
this.kty = kty;
382-
this.alg = alg;
383-
}
384-
385-
@Override
386-
public String name() {
387-
return alg;
388-
}
389-
390-
@Override
391-
public Signer signer() throws GeneralSecurityException {
392-
Signature signature = JWS.getSignature(alg);
393-
// the length of the signature. This is derived from the algorithm name
394-
// this will help to cope with signatures that are longer (yet valid) than
395-
// the expected result
396-
int len = getSignatureLength(alg, publicKey);
397-
return new Signer() {
398-
@Override
399-
public synchronized byte[] sign(byte[] data) throws GeneralSecurityException {
400-
if (privateKey == null) {
401-
throw new IllegalStateException("JWK doesn't contain secKey material");
402-
}
403-
signature.initSign(privateKey);
404-
signature.update(data);
405-
byte[] sig = signature.sign();
406-
switch (kty) {
407-
case "EC":
408-
return JWS.toJWS(sig, len);
409-
default:
410-
return sig;
411-
}
412-
}
413-
@Override
414-
public synchronized boolean verify(byte[] expected, byte[] payload) throws GeneralSecurityException {
415-
if (publicKey == null) {
416-
throw new IllegalStateException("JWK doesn't contain pubKey material");
417-
}
418-
signature.initVerify(publicKey);
419-
signature.update(payload);
420-
switch (kty) {
421-
case "EC":
422-
// JCA EC signatures expect ASN1 formatted signatures
423-
// while JWS uses it's own format (R+S), while this will be true
424-
// for all JWS, it may not be true for COSE keys
425-
if (!JWS.isASN1(expected)) {
426-
expected = JWS.toASN1(expected);
427-
}
428-
break;
429-
}
430-
if (expected.length < len) {
431-
// need to adapt the expectation to make the RSA? engine happy
432-
byte[] normalized = new byte[len];
433-
System.arraycopy(expected, 0, normalized, 0, expected.length);
434-
return signature.verify(normalized);
435-
} else {
436-
return signature.verify(expected);
437-
}
438-
}
439-
};
440-
}
441-
}
442-
443340
private JWK(String algorithm, Mac mac) throws NoSuchAlgorithmException {
444341

445342
kid = null;
@@ -780,23 +677,19 @@ public String kty() {
780677
if (signingAlgorithm instanceof MacSigningAlgorithm) {
781678
return "oct";
782679
} else {
783-
return ((PubKeySigningAlgorithm)signingAlgorithm).kty;
680+
return ((PubKeySigningAlgorithm)signingAlgorithm).kty();
784681
}
785682
}
786683

787-
public Mac mac() {
788-
return signingAlgorithm instanceof MacSigningAlgorithm ? ((MacSigningAlgorithm)signingAlgorithm).mac : null;
789-
}
790-
791684
public SigningAlgorithm signingAlgorithm() {
792685
return signingAlgorithm;
793686
}
794687

795688
public PublicKey publicKey() {
796-
return signingAlgorithm instanceof PubKeySigningAlgorithm ? ((PubKeySigningAlgorithm)signingAlgorithm).publicKey : null;
689+
return signingAlgorithm instanceof PubKeySigningAlgorithm ? ((PubKeySigningAlgorithm)signingAlgorithm).publicKey() : null;
797690
}
798691

799692
public PrivateKey privateKey() {
800-
return signingAlgorithm instanceof PubKeySigningAlgorithm ? ((PubKeySigningAlgorithm)signingAlgorithm).privateKey : null;
693+
return signingAlgorithm instanceof PubKeySigningAlgorithm ? ((PubKeySigningAlgorithm)signingAlgorithm).privateKey() : null;
801694
}
802695
}

vertx-auth-common/src/main/java/io/vertx/ext/auth/impl/jose/JWT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ public JWT addJWK(JWK jwk) {
6868
if (jwk.use() == null || "sig".equals(jwk.use())) {
6969
List<JWS> current;
7070
synchronized (this) {
71-
if (jwk.mac() != null || jwk.publicKey() != null) {
71+
if (jwk.signingAlgorithm().canVerify()) {
7272
current = VERIFY.computeIfAbsent(jwk.getAlgorithm(), k -> new ArrayList<>());
7373
addJWK(current, jwk);
7474
}
75-
if (jwk.mac() != null || jwk.privateKey() != null) {
75+
if (jwk.signingAlgorithm().canSign()) {
7676
current = SIGN.computeIfAbsent(jwk.getAlgorithm(), k -> new ArrayList<>());
7777
addJWK(current, jwk);
7878
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2025 Red Hat, Inc.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* and Apache License v2.0 which accompanies this distribution.
7+
*
8+
* The Eclipse Public License is available at
9+
* http://www.eclipse.org/legal/epl-v10.html
10+
*
11+
* The Apache License v2.0 is available at
12+
* http://www.opensource.org/licenses/apache2.0.php
13+
*
14+
* You may elect to redistribute this code under either of these licenses.
15+
*/
16+
package io.vertx.ext.auth.impl.jose;
17+
18+
import javax.crypto.Mac;
19+
import java.security.MessageDigest;
20+
21+
/**
22+
* @author Paulo Lopes
23+
*/
24+
class MacSigningAlgorithm implements SigningAlgorithm {
25+
26+
private final String name;
27+
private final Mac mac;
28+
29+
MacSigningAlgorithm(String name, Mac mac) {
30+
this.name = name;
31+
this.mac = mac;
32+
}
33+
34+
@Override
35+
public boolean canSign() {
36+
return true;
37+
}
38+
39+
@Override
40+
public boolean canVerify() {
41+
return true;
42+
}
43+
44+
@Override
45+
public String name() {
46+
return name;
47+
}
48+
49+
@Override
50+
public Signer signer() {
51+
return new Signer() {
52+
@Override
53+
public byte[] sign(byte[] data) {
54+
synchronized (MacSigningAlgorithm.this) {
55+
return mac.doFinal(data);
56+
}
57+
}
58+
59+
@Override
60+
public synchronized boolean verify(byte[] expected, byte[] payload) {
61+
synchronized (MacSigningAlgorithm.this) {
62+
return MessageDigest.isEqual(expected, sign(payload));
63+
}
64+
}
65+
};
66+
}
67+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2025 Red Hat, Inc.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* and Apache License v2.0 which accompanies this distribution.
7+
*
8+
* The Eclipse Public License is available at
9+
* http://www.eclipse.org/legal/epl-v10.html
10+
*
11+
* The Apache License v2.0 is available at
12+
* http://www.opensource.org/licenses/apache2.0.php
13+
*
14+
* You may elect to redistribute this code under either of these licenses.
15+
*/
16+
package io.vertx.ext.auth.impl.jose;
17+
18+
import java.security.GeneralSecurityException;
19+
import java.security.PrivateKey;
20+
import java.security.PublicKey;
21+
import java.security.Signature;
22+
23+
import static io.vertx.ext.auth.impl.jose.JWS.getSignatureLength;
24+
25+
/**
26+
* @author Paulo Lopes
27+
*/
28+
class PubKeySigningAlgorithm implements SigningAlgorithm {
29+
30+
private final String kty;
31+
private final String alg;
32+
private final PrivateKey privateKey;
33+
private final PublicKey publicKey;
34+
35+
PubKeySigningAlgorithm(String kty, String alg, PrivateKey privateKey, PublicKey publicKey) {
36+
this.privateKey = privateKey;
37+
this.publicKey = publicKey;
38+
this.kty = kty;
39+
this.alg = alg;
40+
}
41+
42+
public String kty() {
43+
return kty;
44+
}
45+
46+
public PrivateKey privateKey() {
47+
return privateKey;
48+
}
49+
50+
public PublicKey publicKey() {
51+
return publicKey;
52+
}
53+
54+
@Override
55+
public boolean canSign() {
56+
return privateKey != null;
57+
}
58+
59+
@Override
60+
public boolean canVerify() {
61+
return publicKey != null;
62+
}
63+
64+
@Override
65+
public String name() {
66+
return alg;
67+
}
68+
69+
@Override
70+
public Signer signer() throws GeneralSecurityException {
71+
Signature signature = JWS.getSignature(alg);
72+
// the length of the signature. This is derived from the algorithm name
73+
// this will help to cope with signatures that are longer (yet valid) than
74+
// the expected result
75+
int len = getSignatureLength(alg, publicKey);
76+
return new Signer() {
77+
@Override
78+
public synchronized byte[] sign(byte[] data) throws GeneralSecurityException {
79+
if (privateKey == null) {
80+
throw new IllegalStateException("JWK doesn't contain secKey material");
81+
}
82+
signature.initSign(privateKey);
83+
signature.update(data);
84+
byte[] sig = signature.sign();
85+
switch (kty) {
86+
case "EC":
87+
return JWS.toJWS(sig, len);
88+
default:
89+
return sig;
90+
}
91+
}
92+
93+
@Override
94+
public synchronized boolean verify(byte[] expected, byte[] payload) throws GeneralSecurityException {
95+
if (publicKey == null) {
96+
throw new IllegalStateException("JWK doesn't contain pubKey material");
97+
}
98+
signature.initVerify(publicKey);
99+
signature.update(payload);
100+
switch (kty) {
101+
case "EC":
102+
// JCA EC signatures expect ASN1 formatted signatures
103+
// while JWS uses it's own format (R+S), while this will be true
104+
// for all JWS, it may not be true for COSE keys
105+
if (!JWS.isASN1(expected)) {
106+
expected = JWS.toASN1(expected);
107+
}
108+
break;
109+
}
110+
if (expected.length < len) {
111+
// need to adapt the expectation to make the RSA? engine happy
112+
byte[] normalized = new byte[len];
113+
System.arraycopy(expected, 0, normalized, 0, expected.length);
114+
return signature.verify(normalized);
115+
} else {
116+
return signature.verify(expected);
117+
}
118+
}
119+
};
120+
}
121+
}

vertx-auth-common/src/main/java/io/vertx/ext/auth/impl/jose/SigningAlgorithm.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ public interface SigningAlgorithm {
66

77
String name();
88

9+
boolean canSign();
10+
11+
boolean canVerify();
12+
913
Signer signer() throws GeneralSecurityException;
1014

1115
}

0 commit comments

Comments
 (0)