@@ -67,6 +67,51 @@ public static final class PBES2Params {
6767 private byte [] salt ;
6868 private IvParameterSpec ivSpec ;
6969
70+ /*
71+ * Initialize a PBES2Params instance. May generate random salt and
72+ * IV if not passed and the operation is encryption. If initialization
73+ * fails, values are reset. Used by PBES2Params and P11PBECipher
74+ * (SunPKCS11).
75+ */
76+ public void initialize (int blkSize , int opmode , int iCount , byte [] salt ,
77+ AlgorithmParameterSpec params , SecureRandom random )
78+ throws InvalidAlgorithmParameterException {
79+ try {
80+ boolean doEncrypt = ((opmode == Cipher .ENCRYPT_MODE ) ||
81+ (opmode == Cipher .WRAP_MODE ));
82+ if (params instanceof PBEParameterSpec pbeParams ) {
83+ params = pbeParams .getParameterSpec ();
84+ }
85+ if (params instanceof IvParameterSpec iv ) {
86+ this .ivSpec = iv ;
87+ } else if (params == null && doEncrypt ) {
88+ byte [] ivBytes = new byte [blkSize ];
89+ random .nextBytes (ivBytes );
90+ this .ivSpec = new IvParameterSpec (ivBytes );
91+ } else {
92+ throw new InvalidAlgorithmParameterException ("Wrong " +
93+ "parameter type: IvParameterSpec " +
94+ (doEncrypt ? "or null " : "" ) + "expected" );
95+ }
96+ this .iCount = iCount ;
97+ if (salt == null ) {
98+ if (doEncrypt ) {
99+ salt = new byte [DEFAULT_SALT_LENGTH ];
100+ random .nextBytes (salt );
101+ } else {
102+ throw new InvalidAlgorithmParameterException ("Salt " +
103+ "needed for decryption" );
104+ }
105+ }
106+ this .salt = salt ;
107+ } catch (InvalidAlgorithmParameterException e ) {
108+ this .ivSpec = null ;
109+ this .iCount = 0 ;
110+ this .salt = null ;
111+ throw e ;
112+ }
113+ }
114+
70115 /*
71116 * Obtain an IvParameterSpec for Cipher services. This method returns
72117 * null when the state is not initialized. Used by PBES2Core (SunJCE)
@@ -77,116 +122,84 @@ public IvParameterSpec getIvSpec() {
77122 }
78123
79124 /*
80- * Obtain AlgorithmParameters for Cipher services. If the state is not
81- * initialized, this method will generate new values randomly or assign
82- * from defaults. If the state is initialized, existing values will be
83- * returned. Used by PBES2Core (SunJCE) and P11PBECipher (SunPKCS11).
125+ * Obtain AlgorithmParameters for Cipher services. This method will
126+ * initialize PBES2Params if needed, generating new values randomly or
127+ * assigning from defaults. If PBES2Params is initialized, existing
128+ * values will be returned. Used by PBES2Core (SunJCE) and
129+ * P11PBECipher (SunPKCS11).
84130 */
85131 public AlgorithmParameters getAlgorithmParameters (int blkSize ,
86132 String pbeAlgo , Provider algParamsProv , SecureRandom random ) {
87- AlgorithmParameters params = null ;
88- if (salt == null ) {
89- // generate random salt and use default iteration count
90- salt = new byte [DEFAULT_SALT_LENGTH ];
91- random .nextBytes (salt );
92- iCount = DEFAULT_ITERATIONS ;
93- }
94- if (ivSpec == null ) {
95- // generate random IV
96- byte [] ivBytes = new byte [blkSize ];
97- random .nextBytes (ivBytes );
98- ivSpec = new IvParameterSpec (ivBytes );
99- }
100- PBEParameterSpec pbeSpec = new PBEParameterSpec (
101- salt , iCount , ivSpec );
133+ AlgorithmParameters params ;
102134 try {
135+ if (iCount == 0 && salt == null && ivSpec == null ) {
136+ initialize (blkSize , Cipher .ENCRYPT_MODE , DEFAULT_ITERATIONS ,
137+ null , null , random );
138+ }
103139 params = AlgorithmParameters .getInstance (pbeAlgo ,
104140 algParamsProv );
105- params .init (pbeSpec );
141+ params .init (new PBEParameterSpec ( salt , iCount , ivSpec ) );
106142 } catch (NoSuchAlgorithmException nsae ) {
107143 // should never happen
108144 throw new RuntimeException ("AlgorithmParameters for "
109145 + pbeAlgo + " not configured" );
110146 } catch (InvalidParameterSpecException ipse ) {
111147 // should never happen
112148 throw new RuntimeException ("PBEParameterSpec not supported" );
149+ } catch (InvalidAlgorithmParameterException iape ) {
150+ // should never happen
151+ throw new RuntimeException ("Error initializing PBES2Params" );
113152 }
114153 return params ;
115154 }
116155
117156 /*
118- * Obtain a PBEKeySpec for Cipher services, after key and parameters
119- * validation, random generation or assignment from defaults. Used by
120- * PBES2Core (SunJCE) and P11PBECipher (SunPKCS11).
157+ * Initialize PBES2Params and obtain a PBEKeySpec for Cipher services.
158+ * Data from the key, parameters, defaults or random may be used for
159+ * initialization. Used by PBES2Core (SunJCE) and P11PBECipher
160+ * (SunPKCS11).
121161 */
122162 public PBEKeySpec getPBEKeySpec (int blkSize , int keyLength , int opmode ,
123163 Key key , AlgorithmParameterSpec params , SecureRandom random )
124164 throws InvalidKeyException , InvalidAlgorithmParameterException {
125165 if (key == null ) {
126166 throw new InvalidKeyException ("Null key" );
127167 }
128-
129- char [] passwdChars = null ;
130- salt = null ;
131- iCount = 0 ;
132- ivSpec = null ;
133168 PBEKeySpec pbeSpec ;
134169 byte [] passwdBytes ;
170+ char [] passwdChars = null ;
135171 if (!(key .getAlgorithm ().regionMatches (true , 0 , "PBE" , 0 , 3 )) ||
136172 (passwdBytes = key .getEncoded ()) == null ) {
137173 throw new InvalidKeyException ("Missing password" );
138174 }
139175 try {
140- boolean doEncrypt = ((opmode == Cipher .ENCRYPT_MODE ) ||
141- (opmode == Cipher .WRAP_MODE ));
142-
176+ int iCountInit ;
177+ byte [] saltInit ;
143178 // Extract from the supplied PBE params, if present
144179 if (params instanceof PBEParameterSpec pbeParams ) {
145180 // salt should be non-null per PBEParameterSpec
146- salt = check (pbeParams .getSalt ());
147- iCount = check (pbeParams .getIterationCount ());
148- AlgorithmParameterSpec ivParams =
149- pbeParams .getParameterSpec ();
150- if (ivParams instanceof IvParameterSpec iv ) {
151- ivSpec = iv ;
152- } else if (ivParams == null && doEncrypt ) {
153- // generate random IV
154- byte [] ivBytes = new byte [blkSize ];
155- random .nextBytes (ivBytes );
156- ivSpec = new IvParameterSpec (ivBytes );
157- } else {
158- throw new InvalidAlgorithmParameterException (
159- "Wrong parameter type: IV expected" );
160- }
161- } else if (params == null && doEncrypt ) {
181+ iCountInit = check (pbeParams .getIterationCount ());
182+ saltInit = check (pbeParams .getSalt ());
183+ } else if (params == null ) {
162184 // Try extracting from the key if present. If unspecified,
163- // PBEKey returns null and 0 respectively.
185+ // PBEKey returns 0 and null respectively.
164186 if (key instanceof javax .crypto .interfaces .PBEKey pbeKey ) {
165- salt = check (pbeKey .getSalt ());
166- iCount = check (pbeKey .getIterationCount ());
167- }
168- if (salt == null ) {
169- // generate random salt
170- salt = new byte [DEFAULT_SALT_LENGTH ];
171- random .nextBytes (salt );
172- }
173- if (iCount == 0 ) {
174- // use default iteration count
175- iCount = DEFAULT_ITERATIONS ;
187+ iCountInit = check (pbeKey .getIterationCount ());
188+ saltInit = check (pbeKey .getSalt ());
189+ } else {
190+ iCountInit = DEFAULT_ITERATIONS ;
191+ saltInit = null ;
176192 }
177- // generate random IV
178- byte [] ivBytes = new byte [blkSize ];
179- random .nextBytes (ivBytes );
180- ivSpec = new IvParameterSpec (ivBytes );
181193 } else {
182194 throw new InvalidAlgorithmParameterException (
183195 "Wrong parameter type: PBE expected" );
184196 }
197+ initialize (blkSize , opmode , iCountInit , saltInit , params ,
198+ random );
185199 passwdChars = new char [passwdBytes .length ];
186200 for (int i = 0 ; i < passwdChars .length ; i ++) {
187201 passwdChars [i ] = (char ) (passwdBytes [i ] & 0x7f );
188202 }
189-
190203 pbeSpec = new PBEKeySpec (passwdChars , salt , iCount , keyLength );
191204 } finally {
192205 // password char[] was cloned in PBEKeySpec constructor,
0 commit comments