/*
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
*
* 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.cloud.bridge.util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.axis2.AxisFault;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
/**
* Both the SOAP code and the DIME implementation in the REST servlet need
* this authentication functionality.
*/
public class S3SoapAuth {
protected final static Logger logger = Logger.getLogger(S3SoapAuth.class);
public S3SoapAuth() {
}
public static void verifySignature( String givenSignature, String operation, String timestamp, String accessKey, String secretKey )
throws AxisFault {
// -> calculate RFC 2104 HMAC-SHA1 digest over the constructed string
String signString = "AmazonS3" + operation + timestamp;
String calSig = calculateRFC2104HMAC( signString, secretKey );
if ( null == calSig || !givenSignature.equals( calSig ))
{
logger.error( "Signature mismatch, [" + givenSignature + "] [" + calSig + "] over [" + signString + "]" );
throw new AxisFault( "Authentication signature mismatch on AccessKey: [" + accessKey + "] [" + operation + "]",
"Client.SignatureDoesNotMatch" );
}
}
/**
* Create a signature by the following method:
* new String( Base64( SHA1( key, byte array )))
*
* @param signIt - the data to generate a keyed HMAC over
* @param secretKey - the user's unique key for the HMAC operation
* @return String - the recalculated string
*/
private static String calculateRFC2104HMAC( String signIt, String secretKey ) {
String result = null;
try
{ SecretKeySpec key = new SecretKeySpec( secretKey.getBytes(), "HmacSHA1" );
Mac hmacSha1 = Mac.getInstance( "HmacSHA1" );
hmacSha1.init( key );
byte [] rawHmac = hmacSha1.doFinal( signIt.getBytes());
result = new String( Base64.encodeBase64( rawHmac ));
} catch( Exception e ) {
logger.error( "Failed to generate keyed HMAC on soap request: " + e.getMessage());
return null;
}
return result.trim();
}
}