diff --git a/magnolia-core/pom.xml b/magnolia-core/pom.xml index 73b9aa0..1cae0ae 100644 --- a/magnolia-core/pom.xml +++ b/magnolia-core/pom.xml @@ -40,14 +40,10 @@ org.mindrot jbcrypt - - org.bouncycastle - bcprov-ext-jdk16 - - - org.bouncycastle - bcpg-jdk16 - + + org.bouncycastle + bcprov-jdk15on + com.google.inject guice diff --git a/magnolia-core/src/main/java/info/magnolia/cms/security/SecurityUtil.java b/magnolia-core/src/main/java/info/magnolia/cms/security/SecurityUtil.java index 9c7056e..eee24d8 100644 --- a/magnolia-core/src/main/java/info/magnolia/cms/security/SecurityUtil.java +++ b/magnolia-core/src/main/java/info/magnolia/cms/security/SecurityUtil.java @@ -47,34 +47,32 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.math.BigInteger; import java.security.DigestInputStream; import java.security.DigestOutputStream; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Security; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; +import java.security.SecureRandom; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.commons.lang.StringUtils; -import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.AsymmetricBlockCipher; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.engines.RSABlindedEngine; +import org.bouncycastle.crypto.generators.RSAKeyPairGenerator; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; +import org.bouncycastle.crypto.util.PrivateKeyFactory; +import org.bouncycastle.crypto.util.PrivateKeyInfoFactory; +import org.bouncycastle.crypto.util.PublicKeyFactory; +import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; import org.mindrot.jbcrypt.BCrypt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,6 +90,10 @@ public static final String SHA1 = "SHA-1"; //$NON-NLS-1$ public static final String MD5 = "MD5"; //$NON-NLS-1$ + + /** defaults as in default jce KeyGenerator */ + final static BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001); + final static int defaultTests = 12; /** * There are five (5) FIPS-approved* algorithms for generating a condensed representation of a message (message @@ -101,17 +103,7 @@ public static final String SHA384 = "SHA-384"; //$NON-NLS-1$ public static final String SHA512 = "SHA-512"; //$NON-NLS-1$ - /** - * Encryption algorithm used ... if you are ever changing this, keep in mind underlying impl relies on padding! - */ - - private static final String ALGORITHM = "RSA"; - private static Logger log = LoggerFactory.getLogger(SecurityUtil.class); - - static { - Security.addProvider(new BouncyCastleProvider()); - } /** * Checks if the currently acting user is anonymous. @@ -128,6 +120,10 @@ public static String decrypt(String pass) throws SecurityException { return decrypt(pass, getPublicKey()); + } + + private static AsymmetricBlockCipher createCipher(){ + return new RSABlindedEngine(); } public static String decrypt(String message, String encodedKey) throws SecurityException { @@ -140,21 +136,14 @@ byte[] binaryKey = hexToByteArray(encodedKey); // create RSA public key cipher - Cipher pkCipher = Cipher.getInstance(ALGORITHM, "BC"); - try { - // create private key - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(binaryKey); - KeyFactory kf = KeyFactory.getInstance(ALGORITHM, "BC"); - PublicKey pk = kf.generatePublic(publicKeySpec); - pkCipher.init(Cipher.DECRYPT_MODE, pk); - - } catch (InvalidKeySpecException e) { - // decrypting with private key? - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(binaryKey); - KeyFactory kf = KeyFactory.getInstance(ALGORITHM, "BC"); - PrivateKey pk = kf.generatePrivate(privateKeySpec); - pkCipher.init(Cipher.DECRYPT_MODE, pk); - } + AsymmetricBlockCipher pkCipher = createCipher(); + AsymmetricKeyParameter params; + try{ + params = PublicKeyFactory.createKey(binaryKey); + }catch(IOException ex){ + params = PrivateKeyFactory.createKey(binaryKey); + } + pkCipher.init(false, params); // decrypt String[] chunks = StringUtils.split(message, ";"); @@ -164,28 +153,16 @@ StringBuilder clearText = new StringBuilder(); for (String chunk : chunks) { byte[] byteChunk = hexToByteArray(chunk); - clearText.append(new String(pkCipher.doFinal(byteChunk), "UTF-8")); + clearText.append(new String(pkCipher.processBlock(byteChunk, 0, byteChunk.length), "UTF-8")); } return clearText.toString(); } catch (NumberFormatException e) { throw new SecurityException("The encrypted information is corrupted or incomplete. Please make sure someone is not trying to intercept or modify encrypted message.", e); } catch (IOException e) { throw new SecurityException("Failed to read authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("Failed to read authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchPaddingException e) { - throw new SecurityException("Failed to read authentication string. Please use Java version with cryptography support.", e); - } catch (InvalidKeySpecException e) { - throw new SecurityException("Failed to read authentication string. Please use Java version with cryptography support.", e); - } catch (InvalidKeyException e) { - throw new SecurityException("Failed to read authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchProviderException e) { - throw new SecurityException("Failed to find encryption provider. Please use Java version with cryptography support.", e); - } catch (IllegalBlockSizeException e) { - throw new SecurityException("Failed to decrypt message. It might have been corrupted during transport.", e); - } catch (BadPaddingException e) { - throw new SecurityException("Failed to decrypt message. It might have been corrupted during transport.", e); - } + } catch (InvalidCipherTextException e) { + throw new SecurityException("Failed to decrypt message. It might have been corrupted during transport.", e); + } } @@ -203,23 +180,14 @@ } byte[] binaryKey = hexToByteArray(encodedKey); - // create RSA public key cipher - Cipher pkCipher = Cipher.getInstance(ALGORITHM, "BC"); - try { - // create private key - PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(binaryKey); - KeyFactory kf = KeyFactory.getInstance(ALGORITHM, "BC"); - PrivateKey pk = kf.generatePrivate(privateKeySpec); - - pkCipher.init(Cipher.ENCRYPT_MODE, pk); - } catch (InvalidKeySpecException e) { - // encrypting with public key? - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(binaryKey); - KeyFactory kf = KeyFactory.getInstance(ALGORITHM, "BC"); - PublicKey pk = kf.generatePublic(publicKeySpec); - - pkCipher.init(Cipher.ENCRYPT_MODE, pk); - } + AsymmetricBlockCipher pkCipher = createCipher(); + AsymmetricKeyParameter params; + try{ + params = PrivateKeyFactory.createKey(binaryKey); + }catch(IOException ex){ + params = PublicKeyFactory.createKey(binaryKey); + } + pkCipher.init(true, params); // encrypt byte[] bytes = message.getBytes("UTF-8"); @@ -230,7 +198,7 @@ byte[] tmp = new byte[Math.min(bytes.length - start, binaryKey.length / 8)]; System.arraycopy(bytes, start, tmp, 0, tmp.length); start += tmp.length; - byte[] encrypted = pkCipher.doFinal(tmp); + byte[] encrypted = pkCipher.processBlock(tmp, 0, tmp.length); chaos.append(byteArrayToHex(encrypted)); chaos.append(";"); } @@ -240,21 +208,9 @@ } catch (IOException e) { throw new SecurityException("Failed to create authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("Failed to create authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchPaddingException e) { - throw new SecurityException("Failed to create authentication string. Please use Java version with cryptography support.", e); - } catch (InvalidKeySpecException e) { - throw new SecurityException("Failed to create authentication string. Please use Java version with cryptography support.", e); - } catch (InvalidKeyException e) { - throw new SecurityException("Failed to create authentication string. Please use Java version with cryptography support.", e); - } catch (NoSuchProviderException e) { - throw new SecurityException("Failed to find encryption provider. Please use Java version with cryptography support.", e); - } catch (IllegalBlockSizeException e) { + } catch (InvalidCipherTextException e) { throw new SecurityException("Failed to encrypt string. Please use Java version with cryptography support.", e); - } catch (BadPaddingException e) { - throw new SecurityException("Failed to encrypt string. Please use Java version with cryptography support.", e); - } + } } public static String getPrivateKey() { @@ -340,10 +296,19 @@ } public static MgnlKeyPair generateKeyPair(int keyLength) throws NoSuchAlgorithmException { - KeyPairGenerator kgen = KeyPairGenerator.getInstance(ALGORITHM); - kgen.initialize(keyLength); - KeyPair key = kgen.genKeyPair(); - return new MgnlKeyPair(byteArrayToHex(key.getPrivate().getEncoded()), byteArrayToHex(key.getPublic().getEncoded())); + RSAKeyPairGenerator kgen = new RSAKeyPairGenerator(); + kgen.init(new RSAKeyGenerationParameters(defaultPublicExponent, + new SecureRandom(), keyLength, defaultTests)); + AsymmetricCipherKeyPair key = kgen.generateKeyPair(); + try { + String privateKeyHex = byteArrayToHex(PrivateKeyInfoFactory + .createPrivateKeyInfo(key.getPrivate()).getEncoded()); + String publicKeyHex = byteArrayToHex(SubjectPublicKeyInfoFactory + .createSubjectPublicKeyInfo(key.getPublic()).getEncoded()); + return new MgnlKeyPair(privateKeyHex, publicKeyHex); + } catch (IOException e) { + throw new NoSuchAlgorithmException(e); + } } /** diff --git a/pom.xml b/pom.xml index 880705c..f4d51b1 100644 --- a/pom.xml +++ b/pom.xml @@ -314,9 +314,15 @@ org.bouncycastle - bcprov-jdk16 + bcprov-jdk16 1.46 + + org.bouncycastle + bcprov-jdk15on + 1.49 + + org.bouncycastle bcprov-ext-jdk16