/*
* Copyright [2013] [Cloud4SOA, www.cloud4soa.eu]
*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 eu.cloud4soa.adapter.rest.util;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
import eu.cloud4soa.adapter.rest.auth.AuthenticationPropertyExclusionProvider;
import eu.cloud4soa.adapter.rest.auth.Credentials;
import eu.cloud4soa.adapter.rest.auth.CustomerCredentials;
import eu.cloud4soa.adapter.rest.request.Request;
/**
*
* @author Denis Neuling (dn@cloudcontrol.de)
*/
public class EncryptionUtil {
public static final String CIPHER = "SHA1";
public static final int SEEDSIZE = 48;
/**
* Creates an hash of all alphabetic ordered properties of the given request
* by passing by the credentials
*
* @param request
* the request plus the inquired hash
* @param credentials
* the credentials to use to authenticate
* @return request the verified request
* @throws UnsupportedEncodingException
* @throws NoSuchAlgorithmException
*/
public static <T> Request<T> encipher(Request<T> request, Credentials credentials) throws NoSuchAlgorithmException, UnsupportedEncodingException {
Field[] declaredFields = ClassUtil.getAllDeclaredFields(request.getClass(), AuthenticationPropertyExclusionProvider.EXCLUSIONS);
Arrays.sort(declaredFields, 0, declaredFields.length, new Comparator<Field>() {
@Override
public int compare(Field f1, Field f2) {
return f1.getName().compareTo(f2.getName());
}
});
StringBuffer buffer = new StringBuffer();
for (Field field : declaredFields) {
String value = ClassUtil.getValueOf(field.getName(), request, request.getClass(), String.class);
if (value != null) {
buffer.append(value);
}
}
buffer.insert(0, new String(credentials.getApiKey()));
buffer.append(new String(credentials.getSecretKey()));
request.setHash(toSHA1(buffer.toString()));
request.setApiKey(credentials.getApiKey());
return request;
}
/**
* Has to generate the key pair.
*
* <strong>Note:</strong> this is only proof of concept.<br>
* The accounting & billing module has to generate the real credentials.
*
* @return Credentials the credentials to use to access the adapter.
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static Credentials generateCredentials() throws NoSuchAlgorithmException {
CustomerCredentials toUse = new CustomerCredentials();
toUse.setApiKey(convertToHex(randomSeed()));
toUse.setSecretKey(convertToHex(randomSeed()));
return toUse;
}
/**
* Generates random byte array
*
* @return bytes random byte array
*/
private static byte[] randomSeed(){
Random r = new Random();
byte[] seed = new byte[SEEDSIZE];
r.nextBytes(seed);
return seed;
}
/**
* self-explanatory
*
* @param unencrypted String
* @return encrypted string / hashed
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static String toSHA1(String unencrypted) throws NoSuchAlgorithmException, UnsupportedEncodingException{
MessageDigest md = MessageDigest.getInstance(CIPHER);
byte[] sha1hash = new byte[40];
md.update(unencrypted.getBytes("UTF-8"), 0, unencrypted.length());
sha1hash = md.digest();
return convertToHex(sha1hash);
}
/**
* Converts byte array to hex string
*
* @param data byte array to encrypt
* @return hex string
*/
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
}