/*
* #%L
* carewebframework
* %%
* Copyright (C) 2008 - 2016 Regenstrief Institute, Inc.
* %%
* 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.
*
* This Source Code Form is also subject to the terms of the Health-Related
* Additional Disclaimer of Warranty and Limitation of Liability available at
*
* http://www.carewebframework.org/licensing/disclaimer.
*
* #L%
*/
package org.carewebframework.api.security;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Digital signature service implementation. To verify a digital signature, the duration property
* must be set (defaults to 5 minutes). To generate a digital signature, the key name and private
* key password properties must be set.
*/
public class DigitalSignature implements IDigitalSignature {
private static final Log log = LogFactory.getLog(DigitalSignature.class);
private int duration = 5;
private String keyName;
private String privateKeyPassword;
private KeyStore keystore;
/**
* Creates an instance of the signature verification service.
*
* @param keystoreLocation Full path to the JKS key store.
*/
public DigitalSignature(String keystoreLocation) {
this(keystoreLocation, "JKS");
}
/**
* Creates an instance of the signature verification service.
*
* @param keystoreLocation Full path to the key store.
* @param keystoreType The keystore type.
*/
public DigitalSignature(String keystoreLocation, String keystoreType) {
super();
try {
keystore = CipherUtil.getKeyStore(keystoreLocation, keystoreType);
} catch (Exception e) {
log.error("Error attempting to load keystore " + keystoreLocation, e);
}
}
/**
* Verifies the validity of the digital signature using stored key name.
*
* @param base64Signature The digital signature.
* @param content The authorization string to which the signature was applied.
* @param timestamp The timestamp of the digital signature.
* @return True if the signature is valid.
* @throws Exception Unspecified exception.
*/
public boolean verify(String base64Signature, String content, String timestamp) throws Exception {
return verify(base64Signature, content, timestamp, keyName);
}
/**
* @see org.carewebframework.api.security.IDigitalSignature#verify(java.lang.String,
* java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public boolean verify(String base64Signature, String content, String timestamp, String keyName) throws Exception {
Certificate cert = keystore.getCertificate(keyName);
if (cert == null) {
log.error(("Missing public key certificate: " + keyName));
return false;
}
return CipherUtil.verify(cert.getPublicKey(), base64Signature, content, timestamp, duration);
}
/**
* @see org.carewebframework.api.security.IDigitalSignature#sign(java.lang.String)
*/
@Override
public String sign(String content) throws Exception {
PrivateKey privateKey = (PrivateKey) keystore.getKey(keyName, privateKeyPassword.toCharArray());
if (privateKey == null) {
throw new SignatureException("No key " + keyName + " found");
}
return CipherUtil.sign(privateKey, content);
}
/**
* Returns the duration, in minutes, that a signed payload will remain valid beyond its
* timestamp.
*
* @return The duration in minutes.
*/
public int getDuration() {
return duration;
}
/**
* Sets the duration, in minutes, that a signed payload will remain valid beyond its timestamp.
*
* @param duration Duration in minutes.
*/
public void setDuration(int duration) {
this.duration = duration;
}
/**
* @see org.carewebframework.api.security.IDigitalSignature#getKeyName()
*/
@Override
public String getKeyName() {
return keyName;
}
/**
* Sets the name of the key that will be used to generate a digital signature.
*
* @param keyName The key name.
*/
public void setKeyName(String keyName) {
this.keyName = keyName;
}
/**
* Returns the password used to extract the private key for purposes of generating a digital
* signature.
*
* @return The private key password.
*/
public String getPrivateKeyPassword() {
return privateKeyPassword;
}
/**
* Sets the password used to extract the private key for purposes of generating a digital
* signature.
*
* @param privateKeyPassword The private key password.
*/
public void setPrivateKeyPassword(String privateKeyPassword) {
this.privateKeyPassword = privateKeyPassword;
}
}