package com.plectix.license.server; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; import javax.crypto.spec.SecretKeySpec; import com.plectix.license.client.LicenseException; import com.plectix.license.client.SecurityUtil; /** * Container of some utility methods that are called only from within the com.plectix.license.server package * and hidden from the client... * * @author ecemis */ public class ServerSecurityUtil { private static final int BLOCK_SIZE = 16; /** * Convert a byte array to a hex string. * * @param bytes array of bytes * @return hex string */ protected static final String convertFromBytesToHexString(byte[] bytes) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { int n = (new Byte(bytes[i])).intValue(); if (n < 0) { n += 256; } if (n < 16) { stringBuffer.append('0' + Integer.toHexString(n)); } else { stringBuffer.append(Integer.toHexString(n)); } } return stringBuffer.toString(); } /** * Compute an RSA signature (formatted as a hex string) for the specified string, * using the supplied private key * * @param string String to sign * @param privateKey key to sign with * @return hex string of signature * @throws SignatureException * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */ protected static final String computeRSASignature(String string, PrivateKey privateKey) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException { Signature signature = Signature.getInstance(SecurityUtil.SIGNATURE_ALGORITHM); signature.initSign(privateKey); signature.update(SecurityUtil.getBytes(string)); byte[] signatureBytes = signature.sign(); String result = convertFromBytesToHexString(signatureBytes); if (result.length() != SecurityUtil.RSA_SIGNATURE_HEX_SIZE) { throw new IllegalArgumentException("Unexpected length of RSA signature: " + result.length()); } return result; } /** * Read a private key from a hex string of the encoded key bytes. * * @param hex hex string of encoded key bytes * @return private key * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ protected static PrivateKey readPrivateKeyFromHexString(String hex) throws NoSuchAlgorithmException, InvalidKeySpecException { byte[] privEncoded = SecurityUtil.convertFromHexStringToBytes(hex); PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privEncoded); KeyFactory keyFactory = KeyFactory.getInstance(SecurityUtil.SECURITY_ALGORITHM); PrivateKey key = keyFactory.generatePrivate(privKeySpec); return key; } /** * * @param plainText * @param password * @return * @throws LicenseException * @throws NoSuchAlgorithmException * @throws NoSuchPaddingException * @throws GeneralSecurityException */ protected static final String encryptWithPassword(String plainText, String password) throws LicenseException { byte[] keyBytes = SecurityUtil.getKeyBytes(password); SecretKeySpec key = new SecretKeySpec(keyBytes, SecurityUtil.SECRET_KEY_SPEC_ALGORITHM); try { Cipher cipher = Cipher.getInstance(SecurityUtil.CIPHER_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] input = SecurityUtil.getBytes(plainText); byte[] cipherText = new byte[BLOCK_SIZE*(1+input.length/BLOCK_SIZE)]; cipher.doFinal(input, 0, input.length, cipherText, 0); return convertFromBytesToHexString(cipherText); } catch (NoSuchAlgorithmException e) { throw new LicenseException.LicenseGenerationException("Caught NoSuchAlgorithmException: ", plainText, e); } catch (NoSuchPaddingException e) { throw new LicenseException.LicenseGenerationException("Caught NoSuchPaddingException: ", plainText, e); } catch (InvalidKeyException e) { throw new LicenseException.LicenseGenerationException("Caught InvalidKeyException: ", plainText, e); } catch (ShortBufferException e) { throw new LicenseException.LicenseGenerationException("Caught ShortBufferException: ", plainText, e); } catch (IllegalBlockSizeException e) { throw new LicenseException.LicenseGenerationException("Caught IllegalBlockSizeException: ", plainText, e); } catch (BadPaddingException e) { throw new LicenseException.LicenseGenerationException("Caught BadPaddingException: ", plainText, e); } } }