Skip to content
This repository was archived by the owner on Nov 24, 2024. It is now read-only.

Commit 176289f

Browse files
gL1ntslachiewicz
authored andcommitted
Fixed insecure cryptography in PBECipher.java
1 parent 5eaa3f8 commit 176289f

File tree

2 files changed

+13
-63
lines changed

2 files changed

+13
-63
lines changed

src/main/java/org/sonatype/plexus/components/cipher/PBECipher.java

Lines changed: 12 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
/*
2-
* createCipher routine was adopted from http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.10/src/java/org/apache/commons/ssl/OpenSSL.java
3-
* which is distributed under APL-2.0 license: http://www.apache.org/licenses/LICENSE-2.0
4-
*/
5-
61
/*
72
Licensed to the Apache Software Foundation (ASF) under one
83
or more contributor license agreements. See the NOTICE file
@@ -29,10 +24,14 @@ Licensed to the Apache Software Foundation (ASF) under one
2924
import java.security.MessageDigest;
3025
import java.security.NoSuchAlgorithmException;
3126
import java.security.SecureRandom;
27+
import java.security.spec.InvalidKeySpecException;
28+
import java.security.spec.KeySpec;
3229

3330
import javax.crypto.Cipher;
3431
import javax.crypto.NoSuchPaddingException;
32+
import javax.crypto.SecretKeyFactory;
3533
import javax.crypto.spec.IvParameterSpec;
34+
import javax.crypto.spec.PBEKeySpec;
3635
import javax.crypto.spec.SecretKeySpec;
3736

3837
/**
@@ -81,7 +80,7 @@ public String encrypt64( final String clearText, final String password )
8180

8281
byte[] salt = getSalt( SALT_SIZE );
8382

84-
Cipher cipher = createCipher( password.getBytes( STRING_ENCODING ), salt, Cipher.ENCRYPT_MODE );
83+
Cipher cipher = createCipher( password.toCharArray(), salt, Cipher.ENCRYPT_MODE );
8584

8685
byte [] encryptedBytes = cipher.doFinal( clearBytes );
8786

@@ -129,7 +128,7 @@ public String decrypt64( final String encryptedText, final String password )
129128

130129
System.arraycopy( allEncryptedBytes, SALT_SIZE + 1, encryptedBytes, 0, encryptedBytes.length );
131130

132-
Cipher cipher = createCipher( password.getBytes( STRING_ENCODING ), salt, Cipher.DECRYPT_MODE );
131+
Cipher cipher = createCipher( password.toCharArray(), salt, Cipher.DECRYPT_MODE );
133132

134133
byte [] clearBytes = cipher.doFinal( encryptedBytes );
135134

@@ -141,66 +140,17 @@ public String decrypt64( final String encryptedText, final String password )
141140
}
142141
}
143142
//-------------------------------------------------------------------------------
144-
private Cipher createCipher( final byte [] pwdAsBytes, byte [] salt, final int mode )
145-
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
143+
private Cipher createCipher( final char[] pwd, byte [] salt, final int mode )
144+
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, InvalidKeySpecException
146145
{
147146
MessageDigest _digester = MessageDigest.getInstance( DIGEST_ALG );
148147

149148
byte[] keyAndIv = new byte[ SPICE_SIZE * 2 ];
150-
151-
if( salt == null || salt.length == 0 )
152-
{
153-
// Unsalted! Bad idea!
154-
salt = null;
155-
}
156-
157-
byte[] result;
158-
159-
int currentPos = 0;
160-
161-
while (currentPos < keyAndIv.length)
162-
{
163-
_digester.update(pwdAsBytes);
164-
165-
if (salt != null)
166-
{
167-
// First 8 bytes of salt ONLY! That wasn't obvious to me
168-
// when using AES encrypted private keys in "Traditional
169-
// SSLeay Format".
170-
//
171-
// Example:
172-
// DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249
173-
//
174-
// Only the first 8 bytes are salt, but the whole thing is
175-
// re-used again later as the IV. MUCH gnashing of teeth!
176-
_digester.update( salt, 0, 8 );
177-
}
178-
result = _digester.digest();
179-
180-
int stillNeed = keyAndIv.length - currentPos;
181-
182-
// Digest gave us more than we need. Let's truncate it.
183-
if (result.length > stillNeed)
184-
{
185-
byte[] b = new byte[stillNeed];
186-
187-
System.arraycopy(result, 0, b, 0, b.length);
188-
189-
result = b;
190-
}
191-
192-
System.arraycopy(result, 0, keyAndIv, currentPos, result.length);
193-
194-
currentPos += result.length;
195-
196-
if (currentPos < keyAndIv.length)
197-
{
198-
// Next round starts with a hash of the hash.
199-
_digester.reset();
200-
_digester.update(result);
201-
}
202-
}
203149

150+
KeySpec spec = new PBEKeySpec(pwd, salt, 310000, SPICE_SIZE * 16);
151+
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
152+
keyAndIv = factory.generateSecret(spec).getEncoded();
153+
204154
byte[] key = new byte[ SPICE_SIZE ];
205155

206156
byte[] iv = new byte[ SPICE_SIZE ];

src/test/java/org/sonatype/plexus/components/cipher/PBECipherTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class PBECipherTest
3535

3636
String _cleatText = "veryOpenText";
3737

38-
String _encryptedText = "ibeHrdCOonkH7d7YnH7sarQLbwOk1ljkkM/z8hUhl4c=";
38+
String _encryptedText = "F7eMV2QRQF4H0ODCA1nrTGUWacCXVvPemSjaQjGbO6U=";
3939

4040
String _password = "testtest";
4141

0 commit comments

Comments
 (0)