src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java
changeset 51504 c9a3e3cac9c7
parent 47216 71c04702a3d5
equal deleted inserted replaced
51503:0265a70ea2a5 51504:c9a3e3cac9c7
    25 
    25 
    26 package com.sun.crypto.provider;
    26 package com.sun.crypto.provider;
    27 
    27 
    28 import java.security.*;
    28 import java.security.*;
    29 import java.security.spec.*;
    29 import java.security.spec.*;
       
    30 import java.util.Arrays;
    30 import javax.crypto.*;
    31 import javax.crypto.*;
    31 import javax.crypto.spec.*;
    32 import javax.crypto.spec.*;
    32 
    33 
    33 /**
    34 /**
    34  * This class represents password-based encryption as defined by the PKCS #5
    35  * This class represents password-based encryption as defined by the PKCS #5
   171     protected void engineInit(int opmode, Key key,
   172     protected void engineInit(int opmode, Key key,
   172                               AlgorithmParameterSpec params,
   173                               AlgorithmParameterSpec params,
   173                               SecureRandom random)
   174                               SecureRandom random)
   174         throws InvalidKeyException, InvalidAlgorithmParameterException {
   175         throws InvalidKeyException, InvalidAlgorithmParameterException {
   175 
   176 
   176         if ((key == null) ||
   177         if (key == null) {
   177             (key.getEncoded() == null) ||
   178             throw new InvalidKeyException("Null key");
   178             !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
   179         }
   179             throw new InvalidKeyException("Missing password");
   180 
   180         }
   181         byte[] passwdBytes = key.getEncoded();
   181 
   182         char[] passwdChars = null;
   182         // TBD: consolidate the salt, ic and IV parameter checks below
   183         PBEKeySpec pbeSpec;
   183 
   184         try {
   184         // Extract salt and iteration count from the key, if present
   185             if ((passwdBytes == null) ||
   185         if (key instanceof javax.crypto.interfaces.PBEKey) {
   186                     !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
   186             salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
   187                 throw new InvalidKeyException("Missing password");
   187             if (salt != null && salt.length < 8) {
       
   188                 throw new InvalidAlgorithmParameterException(
       
   189                     "Salt must be at least 8 bytes long");
       
   190             }
   188             }
   191             iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
   189 
   192             if (iCount == 0) {
   190             // TBD: consolidate the salt, ic and IV parameter checks below
   193                 iCount = DEFAULT_COUNT;
   191 
   194             } else if (iCount < 0) {
   192             // Extract salt and iteration count from the key, if present
   195                 throw new InvalidAlgorithmParameterException(
   193             if (key instanceof javax.crypto.interfaces.PBEKey) {
   196                     "Iteration count must be a positive number");
   194                 salt = ((javax.crypto.interfaces.PBEKey)key).getSalt();
       
   195                 if (salt != null && salt.length < 8) {
       
   196                     throw new InvalidAlgorithmParameterException(
       
   197                             "Salt must be at least 8 bytes long");
       
   198                 }
       
   199                 iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount();
       
   200                 if (iCount == 0) {
       
   201                     iCount = DEFAULT_COUNT;
       
   202                 } else if (iCount < 0) {
       
   203                     throw new InvalidAlgorithmParameterException(
       
   204                             "Iteration count must be a positive number");
       
   205                 }
   197             }
   206             }
   198         }
   207 
   199 
   208             // Extract salt, iteration count and IV from the params, if present
   200         // Extract salt, iteration count and IV from the params, if present
   209             if (params == null) {
   201         if (params == null) {
   210                 if (salt == null) {
   202             if (salt == null) {
   211                     // generate random salt and use default iteration count
   203                 // generate random salt and use default iteration count
   212                     salt = new byte[DEFAULT_SALT_LENGTH];
   204                 salt = new byte[DEFAULT_SALT_LENGTH];
   213                     random.nextBytes(salt);
   205                 random.nextBytes(salt);
   214                     iCount = DEFAULT_COUNT;
   206                 iCount = DEFAULT_COUNT;
   215                 }
   207             }
   216                 if ((opmode == Cipher.ENCRYPT_MODE) ||
   208             if ((opmode == Cipher.ENCRYPT_MODE) ||
       
   209                         (opmode == Cipher.WRAP_MODE)) {
   217                         (opmode == Cipher.WRAP_MODE)) {
   210                 // generate random IV
   218                     // generate random IV
   211                 byte[] ivBytes = new byte[blkSize];
   219                     byte[] ivBytes = new byte[blkSize];
   212                 random.nextBytes(ivBytes);
   220                     random.nextBytes(ivBytes);
   213                 ivSpec = new IvParameterSpec(ivBytes);
   221                     ivSpec = new IvParameterSpec(ivBytes);
   214             }
   222                 }
   215         } else {
   223             } else {
   216             if (!(params instanceof PBEParameterSpec)) {
   224                 if (!(params instanceof PBEParameterSpec)) {
   217                 throw new InvalidAlgorithmParameterException
   225                     throw new InvalidAlgorithmParameterException
   218                     ("Wrong parameter type: PBE expected");
   226                             ("Wrong parameter type: PBE expected");
   219             }
   227                 }
   220             // salt and iteration count from the params take precedence
   228                 // salt and iteration count from the params take precedence
   221             byte[] specSalt = ((PBEParameterSpec) params).getSalt();
   229                 byte[] specSalt = ((PBEParameterSpec) params).getSalt();
   222             if (specSalt != null && specSalt.length < 8) {
   230                 if (specSalt != null && specSalt.length < 8) {
   223                 throw new InvalidAlgorithmParameterException(
   231                     throw new InvalidAlgorithmParameterException(
   224                     "Salt must be at least 8 bytes long");
   232                             "Salt must be at least 8 bytes long");
   225             }
   233                 }
   226             salt = specSalt;
   234                 salt = specSalt;
   227             int specICount = ((PBEParameterSpec) params).getIterationCount();
   235                 int specICount = ((PBEParameterSpec) params).getIterationCount();
   228             if (specICount == 0) {
   236                 if (specICount == 0) {
   229                 specICount = DEFAULT_COUNT;
   237                     specICount = DEFAULT_COUNT;
   230             } else if (specICount < 0) {
   238                 } else if (specICount < 0) {
   231                 throw new InvalidAlgorithmParameterException(
   239                     throw new InvalidAlgorithmParameterException(
   232                     "Iteration count must be a positive number");
   240                             "Iteration count must be a positive number");
   233             }
   241                 }
   234             iCount = specICount;
   242                 iCount = specICount;
   235 
   243 
   236             AlgorithmParameterSpec specParams =
   244                 AlgorithmParameterSpec specParams =
   237                 ((PBEParameterSpec) params).getParameterSpec();
   245                         ((PBEParameterSpec) params).getParameterSpec();
   238             if (specParams != null) {
   246                 if (specParams != null) {
   239                 if (specParams instanceof IvParameterSpec) {
   247                     if (specParams instanceof IvParameterSpec) {
   240                     ivSpec = (IvParameterSpec)specParams;
   248                         ivSpec = (IvParameterSpec)specParams;
       
   249                     } else {
       
   250                         throw new InvalidAlgorithmParameterException(
       
   251                                 "Wrong parameter type: IV expected");
       
   252                     }
       
   253                 } else if ((opmode == Cipher.ENCRYPT_MODE) ||
       
   254                         (opmode == Cipher.WRAP_MODE)) {
       
   255                     // generate random IV
       
   256                     byte[] ivBytes = new byte[blkSize];
       
   257                     random.nextBytes(ivBytes);
       
   258                     ivSpec = new IvParameterSpec(ivBytes);
   241                 } else {
   259                 } else {
   242                     throw new InvalidAlgorithmParameterException(
   260                     throw new InvalidAlgorithmParameterException(
   243                         "Wrong parameter type: IV expected");
   261                             "Missing parameter type: IV expected");
   244                 }
   262                 }
   245             } else if ((opmode == Cipher.ENCRYPT_MODE) ||
       
   246                         (opmode == Cipher.WRAP_MODE)) {
       
   247                 // generate random IV
       
   248                 byte[] ivBytes = new byte[blkSize];
       
   249                 random.nextBytes(ivBytes);
       
   250                 ivSpec = new IvParameterSpec(ivBytes);
       
   251             } else {
       
   252                 throw new InvalidAlgorithmParameterException(
       
   253                     "Missing parameter type: IV expected");
       
   254             }
   263             }
   255         }
   264 
   256 
   265             passwdChars = new char[passwdBytes.length];
   257         SecretKeySpec cipherKey = null;
   266             for (int i = 0; i < passwdChars.length; i++)
   258         byte[] derivedKey = null;
   267                 passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
   259         byte[] passwdBytes = key.getEncoded();
   268 
   260         char[] passwdChars = new char[passwdBytes.length];
   269             pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength);
   261 
       
   262         for (int i=0; i<passwdChars.length; i++)
       
   263             passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
       
   264 
       
   265         PBEKeySpec pbeSpec =
       
   266             new PBEKeySpec(passwdChars, salt, iCount, keyLength);
       
   267             // password char[] was cloned in PBEKeySpec constructor,
   270             // password char[] was cloned in PBEKeySpec constructor,
   268             // so we can zero it out here
   271             // so we can zero it out here
   269         java.util.Arrays.fill(passwdChars, ' ');
   272         } finally {
   270         java.util.Arrays.fill(passwdBytes, (byte)0x00);
   273             if (passwdChars != null) Arrays.fill(passwdChars, '\0');
       
   274             if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00);
       
   275         }
   271 
   276 
   272         SecretKey s = null;
   277         SecretKey s = null;
   273 
   278 
   274         try {
   279         try {
   275             s = kdf.engineGenerateSecret(pbeSpec);
   280             s = kdf.engineGenerateSecret(pbeSpec);
   278             InvalidKeyException ike =
   283             InvalidKeyException ike =
   279                 new InvalidKeyException("Cannot construct PBE key");
   284                 new InvalidKeyException("Cannot construct PBE key");
   280             ike.initCause(ikse);
   285             ike.initCause(ikse);
   281             throw ike;
   286             throw ike;
   282         }
   287         }
   283         derivedKey = s.getEncoded();
   288         byte[] derivedKey = s.getEncoded();
   284         cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
   289         SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, cipherAlgo);
   285 
   290 
   286         // initialize the underlying cipher
   291         // initialize the underlying cipher
   287         cipher.init(opmode, cipherKey, ivSpec, random);
   292         cipher.init(opmode, cipherKey, ivSpec, random);
   288     }
   293     }
   289 
   294