/*
* Copyright (c) 2011 Lockheed Martin Corporation
*
* 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.eurekastreams.server.service.email;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.util.regex.Pattern;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.eurekastreams.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class to encode and decode person-specific tokens (for use in the email interface).
*/
public class TokenEncoder
{
/** Log. */
private final Logger log = LoggerFactory.getLogger(LogFactory.getClassName());
/** Encryption algorithm to use. */
private final String algorithm;
/** Regex for checking if a string might be a token. */
private static final Pattern TOKEN_PATTERN = Pattern.compile("^[A-Z0-9+/]+={0,2}$", Pattern.CASE_INSENSITIVE);
/**
* Constructor.
*
* @param inAlgorithm
* Encryption algorithm to use.
*/
public TokenEncoder(final String inAlgorithm)
{
algorithm = inAlgorithm;
}
/**
* Encode a data string into a token.
*
* @param content
* Pre-formatted data.
* @param keyBytes
* Key to encrypt token with.
* @return Token.
*/
public String encode(final String content, final byte[] keyBytes)
{
// get the person's key
Key key = new SecretKeySpec(keyBytes, algorithm);
// encrypt the data
byte[] encrypted;
try
{
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key);
encrypted = cipher.doFinal(content.getBytes());
}
catch (GeneralSecurityException ex)
{
log.error("Error encrypting data into token (data: '{}')", content, ex);
return null;
}
// encode the data (base64)
String token = javax.xml.bind.DatatypeConverter.printBase64Binary(encrypted);
return token;
}
/**
* Determines if a string could represent a token.
*
* @param potentialToken
* Token string to check.
* @return If the string may be a token.
*/
public boolean couldBeToken(final String potentialToken)
{
return TOKEN_PATTERN.matcher(potentialToken).matches();
}
/**
* Decodes a token.
*
* @param token
* Token.
* @param keyBytes
* Key to decrypt token with.
* @return Content string.
*/
public String decode(final String token, final byte[] keyBytes)
{
// decode the data (base64)
byte[] encrypted = javax.xml.bind.DatatypeConverter.parseBase64Binary(token);
if (encrypted.length == 0)
{
return null;
}
// get the person's key
Key key = new SecretKeySpec(keyBytes, algorithm);
// decrypt the data
byte[] decrypted;
try
{
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key);
decrypted = cipher.doFinal(encrypted);
}
catch (GeneralSecurityException ex)
{
log.error("Error decrypting data from token", ex);
return null;
}
return new String(decrypted);
}
}