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

Commit ed36a35

Browse files
committed
Componentize
1 parent b8d5b1f commit ed36a35

File tree

9 files changed

+340
-227
lines changed

9 files changed

+340
-227
lines changed

src/main/java/org/codehaus/plexus/components/cipher/PlexusCipher.java

+38-36
Original file line numberDiff line numberDiff line change
@@ -12,74 +12,76 @@
1212
*/
1313
package org.codehaus.plexus.components.cipher;
1414

15+
import java.util.Set;
16+
1517
/**
1618
* @author Oleg Gusakov
1719
*/
1820
public interface PlexusCipher {
21+
22+
/**
23+
* Returns the available cipher algorithms, never {@code null}.
24+
*/
25+
Set<String> availableCiphers();
26+
1927
/**
20-
* encrypt given string with the given passPhrase and encode it into base64
28+
* Encrypt given string with the given alg and passPhrase and encode it into Base64 string.
2129
*
22-
* @param str string to encrypt
23-
* @param passPhrase pass phrase
24-
* @return encrypted str
30+
* @param alg cipher alg to use, never {@code null}
31+
* @param str string to encrypt, never {@code null}
32+
* @param passPhrase pass phrase, never {@code null}
33+
* @return encrypted str, never {@code null}
2534
* @throws PlexusCipherException if encryption fails
2635
*/
27-
String encrypt(String str, String passPhrase) throws PlexusCipherException;
36+
String encrypt(String alg, String str, String passPhrase) throws PlexusCipherException;
2837

2938
/**
30-
* encrypt given string with the given passPhrase, encode it into base64 and return result, wrapped into { }
31-
* decorations
39+
* Encrypt given string with the given alg and passPhrase and encode it into Base64 decorated string.
3240
*
33-
* @param str string to encrypt
34-
* @param passPhrase pass phrase
35-
* @return encrypted and decorated str
41+
* @param alg cipher alg to use, never {@code null}
42+
* @param str string to encrypt, never {@code null}
43+
* @param passPhrase pass phrase, never {@code null}
44+
* @return encrypted and decorated str, never {@code null}
3645
* @throws PlexusCipherException if encryption fails
3746
*/
38-
String encryptAndDecorate(String str, String passPhrase) throws PlexusCipherException;
47+
String encryptAndDecorate(String alg, String str, String passPhrase) throws PlexusCipherException;
3948

4049
/**
41-
* decrypt given base64 encrypted string
50+
* Decrypt given Base64 encoded string with the given alg and passPhrase and return resulting string.
4251
*
43-
* @param str base64 encoded string
44-
* @param passPhrase pass phrase
45-
* @return decrypted str
46-
* @throws PlexusCipherException if decryption fails
52+
* @param alg cipher alg to use, never {@code null}
53+
* @param str string to encrypt, never {@code null}
54+
* @param passPhrase pass phrase, never {@code null}
55+
* @return encrypted and decorated str, never {@code null}
56+
* @throws PlexusCipherException if encryption fails
4757
*/
48-
String decrypt(String str, String passPhrase) throws PlexusCipherException;
58+
String decrypt(String alg, String str, String passPhrase) throws PlexusCipherException;
4959

5060
/**
51-
* decrypt given base64 encoded encrypted string. If string is decorated, decrypt base64 encoded string inside
52-
* decorations
61+
* Decrypt given decorated Base64 encoded string with the given alg and passPhrase and return resulting string.
5362
*
54-
* @param str base64 encoded string
55-
* @param passPhrase pass phrase
56-
* @return decrypted decorated str
57-
* @throws PlexusCipherException if decryption fails
63+
* @param alg cipher alg to use, never {@code null}
64+
* @param str string to encrypt, never {@code null}
65+
* @param passPhrase pass phrase, never {@code null}
66+
* @return encrypted and decorated str, never {@code null}
67+
* @throws PlexusCipherException if encryption fails
5868
*/
59-
String decryptDecorated(String str, String passPhrase) throws PlexusCipherException;
69+
String decryptDecorated(String alg, String str, String passPhrase) throws PlexusCipherException;
6070

6171
/**
62-
* check if given string is decorated
63-
*
64-
* @param str string to check
65-
* @return true if string is encrypted
72+
* Check if given string is decorated.
6673
*/
6774
boolean isEncryptedString(String str);
6875

6976
/**
70-
* return string inside decorations
77+
* Remove decorations from string, if it was decorated.
7178
*
72-
* @param str decorated string
73-
* @return undecorated str
74-
* @throws PlexusCipherException if decryption fails
79+
* @throws PlexusCipherException is string is malformed
7580
*/
7681
String unDecorate(String str) throws PlexusCipherException;
7782

7883
/**
79-
* decorated given string with { and }
80-
*
81-
* @param str string to decorate
82-
* @return decorated str
84+
* Decorates given string.
8385
*/
8486
String decorate(String str);
8587
}

src/main/java/org/codehaus/plexus/components/cipher/internal/PBECipher.java src/main/java/org/codehaus/plexus/components/cipher/internal/AESCBCPKCS5Padding.java

+22-54
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ Licensed to the Apache Software Foundation (ASF) under one
2525
import javax.crypto.spec.IvParameterSpec;
2626
import javax.crypto.spec.PBEKeySpec;
2727
import javax.crypto.spec.SecretKeySpec;
28+
import javax.inject.Named;
29+
import javax.inject.Singleton;
2830

29-
import java.nio.charset.Charset;
3031
import java.nio.charset.StandardCharsets;
3132
import java.security.InvalidAlgorithmParameterException;
3233
import java.security.InvalidKeyException;
@@ -38,107 +39,74 @@ Licensed to the Apache Software Foundation (ASF) under one
3839

3940
import org.codehaus.plexus.components.cipher.PlexusCipherException;
4041

41-
/**
42-
* This class is thread-safe.
43-
*
44-
* @author Oleg Gusakov
45-
*/
46-
public class PBECipher {
47-
protected static final Charset STRING_ENCODING = StandardCharsets.UTF_8;
48-
protected static final int SPICE_SIZE = 16;
49-
protected static final int SALT_SIZE = 8;
50-
protected static final int CHUNK_SIZE = 16;
51-
protected static final String KEY_ALG = "AES";
52-
protected static final String CIPHER_ALG = "AES/CBC/PKCS5Padding";
53-
protected static final int PBE_ITERATIONS = 310000;
42+
@Singleton
43+
@Named(AESCBCPKCS5Padding.CIPHER_ALG)
44+
public class AESCBCPKCS5Padding implements org.codehaus.plexus.components.cipher.internal.Cipher {
45+
public static final String CIPHER_ALG = "AES/CBC/PKCS5Padding";
46+
47+
private static final int SPICE_SIZE = 16;
48+
private static final int SALT_SIZE = 8;
49+
private static final int CHUNK_SIZE = 16;
50+
private static final String KEY_ALG = "AES";
51+
private static final int PBE_ITERATIONS = 310000;
5452
private static final SecureRandom _secureRandom = new SecureRandom();
5553

56-
// ---------------------------------------------------------------
57-
private byte[] getSalt(final int sz) {
54+
private byte[] getSalt(int sz) {
5855
byte[] res = new byte[sz];
59-
6056
_secureRandom.nextBytes(res);
61-
6257
return res;
6358
}
64-
// -------------------------------------------------------------------------------
65-
public String encrypt64(final String clearText, final String password) throws PlexusCipherException {
66-
try {
67-
byte[] clearBytes = clearText.getBytes(STRING_ENCODING);
6859

60+
@Override
61+
public String encrypt(String clearText, String password) throws PlexusCipherException {
62+
try {
63+
byte[] clearBytes = clearText.getBytes(StandardCharsets.UTF_8);
6964
byte[] salt = getSalt(SALT_SIZE);
70-
7165
Cipher cipher = createCipher(password.toCharArray(), salt, Cipher.ENCRYPT_MODE);
72-
7366
byte[] encryptedBytes = cipher.doFinal(clearBytes);
74-
7567
int len = encryptedBytes.length;
76-
7768
byte padLen = (byte) (CHUNK_SIZE - (SALT_SIZE + len + 1) % CHUNK_SIZE);
78-
7969
int totalLen = SALT_SIZE + len + padLen + 1;
80-
8170
byte[] allEncryptedBytes = getSalt(totalLen);
82-
8371
System.arraycopy(salt, 0, allEncryptedBytes, 0, SALT_SIZE);
84-
8572
allEncryptedBytes[SALT_SIZE] = padLen;
86-
8773
System.arraycopy(encryptedBytes, 0, allEncryptedBytes, SALT_SIZE + 1, len);
88-
8974
return Base64.getEncoder().encodeToString(allEncryptedBytes);
9075
} catch (Exception e) {
9176
throw new PlexusCipherException(e.getMessage(), e);
9277
}
9378
}
9479

95-
// -------------------------------------------------------------------------------
96-
public String decrypt64(final String encryptedText, final String password) throws PlexusCipherException {
80+
@Override
81+
public String decrypt(String encryptedText, String password) throws PlexusCipherException {
9782
try {
9883
byte[] allEncryptedBytes = Base64.getDecoder().decode(encryptedText.getBytes());
99-
10084
int totalLen = allEncryptedBytes.length;
101-
10285
byte[] salt = new byte[SALT_SIZE];
103-
10486
System.arraycopy(allEncryptedBytes, 0, salt, 0, SALT_SIZE);
105-
10687
byte padLen = allEncryptedBytes[SALT_SIZE];
107-
10888
byte[] encryptedBytes = new byte[totalLen - SALT_SIZE - 1 - padLen];
109-
11089
System.arraycopy(allEncryptedBytes, SALT_SIZE + 1, encryptedBytes, 0, encryptedBytes.length);
111-
11290
Cipher cipher = createCipher(password.toCharArray(), salt, Cipher.DECRYPT_MODE);
113-
11491
byte[] clearBytes = cipher.doFinal(encryptedBytes);
115-
116-
return new String(clearBytes, STRING_ENCODING);
92+
return new String(clearBytes, StandardCharsets.UTF_8);
11793
} catch (Exception e) {
11894
throw new PlexusCipherException(e.getMessage(), e);
11995
}
12096
}
121-
// -------------------------------------------------------------------------------
122-
private Cipher createCipher(final char[] pwd, byte[] salt, final int mode)
97+
98+
private Cipher createCipher(char[] pwd, byte[] salt, int mode)
12399
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
124100
InvalidAlgorithmParameterException, InvalidKeySpecException {
125-
126101
KeySpec spec = new PBEKeySpec(pwd, salt, PBE_ITERATIONS, SPICE_SIZE * 16);
127102
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
128103
byte[] keyAndIv = factory.generateSecret(spec).getEncoded();
129-
130104
byte[] key = new byte[SPICE_SIZE];
131-
132105
byte[] iv = new byte[SPICE_SIZE];
133-
134106
System.arraycopy(keyAndIv, 0, key, 0, key.length);
135-
136107
System.arraycopy(keyAndIv, key.length, iv, 0, iv.length);
137-
138108
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
139-
140109
cipher.init(mode, new SecretKeySpec(key, KEY_ALG), new IvParameterSpec(iv));
141-
142110
return cipher;
143111
}
144112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
*/
19+
20+
package org.codehaus.plexus.components.cipher.internal;
21+
22+
import javax.crypto.Cipher;
23+
import javax.crypto.NoSuchPaddingException;
24+
import javax.crypto.SecretKeyFactory;
25+
import javax.crypto.spec.GCMParameterSpec;
26+
import javax.crypto.spec.PBEKeySpec;
27+
import javax.crypto.spec.SecretKeySpec;
28+
import javax.inject.Named;
29+
import javax.inject.Singleton;
30+
31+
import java.nio.charset.StandardCharsets;
32+
import java.security.InvalidAlgorithmParameterException;
33+
import java.security.InvalidKeyException;
34+
import java.security.NoSuchAlgorithmException;
35+
import java.security.SecureRandom;
36+
import java.security.spec.InvalidKeySpecException;
37+
import java.security.spec.KeySpec;
38+
import java.util.Base64;
39+
40+
import org.codehaus.plexus.components.cipher.PlexusCipherException;
41+
42+
@Singleton
43+
@Named(AESGCMNoPadding.CIPHER_ALG)
44+
public class AESGCMNoPadding implements org.codehaus.plexus.components.cipher.internal.Cipher {
45+
public static final String CIPHER_ALG = "AES/GCM/NoPadding";
46+
47+
private static final int SPICE_SIZE = 16;
48+
private static final int SALT_SIZE = 8;
49+
private static final int CHUNK_SIZE = 16;
50+
private static final String KEY_ALG = "AES";
51+
private static final int PBE_ITERATIONS = 310000;
52+
private static final SecureRandom _secureRandom = new SecureRandom();
53+
54+
private byte[] getSalt(int sz) {
55+
byte[] res = new byte[sz];
56+
_secureRandom.nextBytes(res);
57+
return res;
58+
}
59+
60+
@Override
61+
public String encrypt(String clearText, String password) throws PlexusCipherException {
62+
try {
63+
byte[] clearBytes = clearText.getBytes(StandardCharsets.UTF_8);
64+
byte[] salt = getSalt(SALT_SIZE);
65+
Cipher cipher = createCipher(password.toCharArray(), salt, Cipher.ENCRYPT_MODE);
66+
byte[] encryptedBytes = cipher.doFinal(clearBytes);
67+
int len = encryptedBytes.length;
68+
byte padLen = (byte) (CHUNK_SIZE - (SALT_SIZE + len + 1) % CHUNK_SIZE);
69+
int totalLen = SALT_SIZE + len + padLen + 1;
70+
byte[] allEncryptedBytes = getSalt(totalLen);
71+
System.arraycopy(salt, 0, allEncryptedBytes, 0, SALT_SIZE);
72+
allEncryptedBytes[SALT_SIZE] = padLen;
73+
System.arraycopy(encryptedBytes, 0, allEncryptedBytes, SALT_SIZE + 1, len);
74+
return Base64.getEncoder().encodeToString(allEncryptedBytes);
75+
} catch (Exception e) {
76+
throw new PlexusCipherException(e.getMessage(), e);
77+
}
78+
}
79+
80+
@Override
81+
public String decrypt(String encryptedText, String password) throws PlexusCipherException {
82+
try {
83+
byte[] allEncryptedBytes = Base64.getDecoder().decode(encryptedText.getBytes());
84+
int totalLen = allEncryptedBytes.length;
85+
byte[] salt = new byte[SALT_SIZE];
86+
System.arraycopy(allEncryptedBytes, 0, salt, 0, SALT_SIZE);
87+
byte padLen = allEncryptedBytes[SALT_SIZE];
88+
byte[] encryptedBytes = new byte[totalLen - SALT_SIZE - 1 - padLen];
89+
System.arraycopy(allEncryptedBytes, SALT_SIZE + 1, encryptedBytes, 0, encryptedBytes.length);
90+
Cipher cipher = createCipher(password.toCharArray(), salt, Cipher.DECRYPT_MODE);
91+
byte[] clearBytes = cipher.doFinal(encryptedBytes);
92+
return new String(clearBytes, StandardCharsets.UTF_8);
93+
} catch (Exception e) {
94+
throw new PlexusCipherException(e.getMessage(), e);
95+
}
96+
}
97+
98+
private Cipher createCipher(char[] pwd, byte[] salt, int mode)
99+
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
100+
InvalidAlgorithmParameterException, InvalidKeySpecException {
101+
KeySpec spec = new PBEKeySpec(pwd, salt, PBE_ITERATIONS, SPICE_SIZE * 16);
102+
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
103+
byte[] keyAndIv = factory.generateSecret(spec).getEncoded();
104+
byte[] key = new byte[SPICE_SIZE];
105+
byte[] iv = new byte[12];
106+
_secureRandom.nextBytes(iv);
107+
System.arraycopy(keyAndIv, 0, key, 0, key.length);
108+
Cipher cipher = Cipher.getInstance(CIPHER_ALG);
109+
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
110+
cipher.init(mode, new SecretKeySpec(key, KEY_ALG), gcmSpec);
111+
return cipher;
112+
}
113+
}

0 commit comments

Comments
 (0)