blob: c36c1605b60c246268b04c005bca7c1da61a9a95 [file] [log] [blame]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package com.google.crypto.tink.jwt;
import com.google.crypto.tink.PrimitiveSet;
import com.google.crypto.tink.PrimitiveWrapper;
import com.google.crypto.tink.Registry;
import com.google.errorprone.annotations.Immutable;
import java.security.GeneralSecurityException;
import java.util.List;
/** The implementation of {@code PrimitiveWrapper<JwtPublicKeyVerify>}. */
class JwtPublicKeyVerifyWrapper
implements PrimitiveWrapper<JwtPublicKeyVerify, JwtPublicKeyVerify> {
private static void validate(PrimitiveSet<JwtPublicKeyVerify> primitiveSet)
throws GeneralSecurityException {
if (primitiveSet.getPrimary() == null) {
throw new GeneralSecurityException("Primitive set has no primary.");
}
if (primitiveSet.getAll().size() != 1 || primitiveSet.getRawPrimitives().isEmpty()) {
throw new GeneralSecurityException("All JWT JwtPublicKeyVerify keys must be raw.");
}
}
@Immutable
private static class WrappedJwtPublicKeyVerify implements JwtPublicKeyVerify {
@SuppressWarnings("Immutable")
private final PrimitiveSet<JwtPublicKeyVerify> primitives;
public WrappedJwtPublicKeyVerify(PrimitiveSet<JwtPublicKeyVerify> primitives) {
this.primitives = primitives;
}
@Override
public VerifiedJwt verifyAndDecode(String compact, JwtValidator validator)
throws GeneralSecurityException {
// All JWT keys are raw.
List<PrimitiveSet.Entry<JwtPublicKeyVerify>> entries = primitives.getRawPrimitives();
GeneralSecurityException interestingException = null;
for (PrimitiveSet.Entry<JwtPublicKeyVerify> entry : entries) {
try {
return entry.getPrimitive().verifyAndDecode(compact, validator);
} catch (GeneralSecurityException e) {
if (e instanceof JwtInvalidException) {
// Keep this exception so that we are able to throw a meaningful message in the end
interestingException = e;
}
// Ignored as we want to continue verification with other raw keys.
}
}
if (interestingException != null) {
throw interestingException;
}
throw new GeneralSecurityException("invalid JWT");
}
}
@Override
public JwtPublicKeyVerify wrap(final PrimitiveSet<JwtPublicKeyVerify> primitives)
throws GeneralSecurityException {
validate(primitives);
return new WrappedJwtPublicKeyVerify(primitives);
}
@Override
public Class<JwtPublicKeyVerify> getPrimitiveClass() {
return JwtPublicKeyVerify.class;
}
@Override
public Class<JwtPublicKeyVerify> getInputPrimitiveClass() {
return JwtPublicKeyVerify.class;
}
/**
* Register the wrapper within the registry.
*
* <p>This is required for calls to {@link Keyset.getPrimitive} with a {@link JwtPublicKeyVerify}
* argument.
*/
public static void register() throws GeneralSecurityException {
Registry.registerPrimitiveWrapper(new JwtPublicKeyVerifyWrapper());
}
}