org.jose4j.jws.BaseSignatureAlgorithm Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2012-2017 Brian Campbell
*
* 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 org.jose4j.jws;
import org.jose4j.jca.ProviderContext;
import org.jose4j.jwa.AlgorithmInfo;
import org.jose4j.jwa.CryptoPrimitive;
import org.jose4j.keys.KeyPersuasion;
import org.jose4j.lang.ExceptionHelp;
import org.jose4j.lang.InvalidKeyException;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
/**
*/
public abstract class BaseSignatureAlgorithm extends AlgorithmInfo implements JsonWebSignatureAlgorithm
{
private final Logger log = LoggerFactory.getLogger(this.getClass());
private AlgorithmParameterSpec algorithmParameterSpec;
public BaseSignatureAlgorithm(String id, String javaAlgo, String keyAlgo)
{
setAlgorithmIdentifier(id);
setJavaAlgorithm(javaAlgo);
setKeyPersuasion(KeyPersuasion.ASYMMETRIC);
setKeyType(keyAlgo);
}
protected void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec)
{
this.algorithmParameterSpec = algorithmParameterSpec;
}
@Override
public boolean verifySignature(byte[] signatureBytes, Key key, byte[] securedInputBytes, ProviderContext providerContext) throws JoseException
{
Signature signature = getSignature(providerContext);
initForVerify(signature, key);
try
{
signature.update(securedInputBytes);
return signature.verify(signatureBytes);
}
catch (SignatureException e)
{
if (log.isDebugEnabled()) {log.debug("Problem verifying " + getAlgorithmIdentifier() + " signature: " + ExceptionHelp.toStringWithCauses(e));}
return false;
}
}
@Override
public CryptoPrimitive prepareForSign(Key key, ProviderContext providerContext) throws JoseException
{
Signature signature = getSignature(providerContext);
initForSign(signature, key, providerContext);
return new CryptoPrimitive(signature);
}
@Override
public byte[] sign(CryptoPrimitive cryptoPrimitive, byte[] securedInputBytes) throws JoseException
{
Signature signature = cryptoPrimitive.getSignature();
try
{
signature.update(securedInputBytes);
return signature.sign();
}
catch (SignatureException e)
{
throw new JoseException("Problem creating signature.", e);
}
}
private void initForSign(Signature signature, Key key, ProviderContext providerContext) throws InvalidKeyException
{
try
{
PrivateKey privateKey = (PrivateKey) key;
SecureRandom secureRandom = providerContext.getSecureRandom();
if (secureRandom == null)
{
signature.initSign(privateKey);
}
else
{
signature.initSign(privateKey, secureRandom);
}
}
catch (java.security.InvalidKeyException e)
{
throw new InvalidKeyException(getBadKeyMessage(key) + "for " + getJavaAlgorithm(), e);
}
}
private void initForVerify(Signature signature, Key key) throws InvalidKeyException
{
try
{
PublicKey publicKey = (PublicKey) key;
signature.initVerify(publicKey);
}
catch (java.security.InvalidKeyException e)
{
throw new InvalidKeyException(getBadKeyMessage(key) + "for " + getJavaAlgorithm(), e);
}
}
private String getBadKeyMessage(Key key)
{
String msg = key == null ? "key is null" : "algorithm=" + key.getAlgorithm();
return "The given key (" + msg + ") is not valid ";
}
private Signature getSignature(ProviderContext providerContext) throws JoseException
{
ProviderContext.Context suppliedKeyProviderContext = providerContext.getSuppliedKeyProviderContext();
String sigProvider = suppliedKeyProviderContext.getSignatureProvider();
String javaAlg = getJavaAlgorithm();
ProviderContext.SignatureAlgorithmOverride algOverride = suppliedKeyProviderContext.getSignatureAlgorithmOverride();
if (algOverride != null && algOverride.getAlgorithmName() != null)
{
javaAlg = algOverride.getAlgorithmName();
}
try
{
Signature signature = sigProvider == null ? Signature.getInstance(javaAlg) : Signature.getInstance(javaAlg, sigProvider);
AlgorithmParameterSpec algorithmParameterSpec = this.algorithmParameterSpec;
if (algOverride != null)
{
algorithmParameterSpec = algOverride.getAlgorithmParameterSpec();
}
if (algorithmParameterSpec != null)
{
try
{
signature.setParameter(algorithmParameterSpec);
}
catch (UnsupportedOperationException e)
{
if (log.isDebugEnabled())
{
log.debug("Unable to set algorithm parameter spec on Signature (java algorithm name: " + javaAlg +
") so ignoring the UnsupportedOperationException and relying on the default parameters.", e);
}
}
}
return signature;
}
catch (NoSuchAlgorithmException e)
{
throw new JoseException("Unable to get an implementation of algorithm name: " + javaAlg, e);
}
catch (InvalidAlgorithmParameterException e)
{
throw new JoseException("Invalid algorithm parameter ("+algorithmParameterSpec+") for: " + javaAlg, e);
}
catch (NoSuchProviderException e)
{
throw new JoseException("Unable to get an implementation of " + javaAlg + " for provider " + sigProvider, e);
}
}
public abstract void validatePrivateKey(PrivateKey privateKey) throws InvalidKeyException;
public void validateSigningKey(Key key) throws InvalidKeyException
{
checkForNullKey(key);
try
{
validatePrivateKey((PrivateKey)key);
}
catch (ClassCastException e)
{
throw new InvalidKeyException(getBadKeyMessage(key) + "(not a private key or is the wrong type of key) for "
+ getJavaAlgorithm() + " / " + getAlgorithmIdentifier() + " " + e);
}
}
public abstract void validatePublicKey(PublicKey publicKey) throws InvalidKeyException;
public void validateVerificationKey(Key key) throws InvalidKeyException
{
checkForNullKey(key);
try
{
validatePublicKey((PublicKey)key);
}
catch (ClassCastException e)
{
throw new InvalidKeyException(getBadKeyMessage(key) + "(not a public key or is the wrong type of key) for "
+ getJavaAlgorithm() + "/" + getAlgorithmIdentifier() + " " + e);
}
}
private void checkForNullKey(Key key) throws InvalidKeyException
{
if (key == null)
{
throw new InvalidKeyException("Key cannot be null");
}
}
@Override
public boolean isAvailable()
{
try
{
Signature signature = getSignature(new ProviderContext());
return signature != null;
}
catch (Exception e)
{
log.debug(getAlgorithmIdentifier() + " via " + getJavaAlgorithm() +
" is NOT available from the underlying JCE (" + ExceptionHelp.toStringWithCauses(e) + ").");
return false;
}
}
}