📄 jcecipherfactory.java
字号:
iv = new byte[IVlen]; iv[0] = (byte)(((secretKey[secretKey.length-1] << 2) | 0xF) ^ secretKey[0]); for (int i = 1; i < BLOCK_LENGTH; i++) iv[i] = (byte)(((secretKey[i-1] << (i%5)) | 0xF) ^ secretKey[i]); for(int i = BLOCK_LENGTH ; i < AES_IV_LENGTH ; i++) { iv[i]=iv[i-BLOCK_LENGTH]; } } else { iv = new byte[BLOCK_LENGTH]; iv[0] = (byte)(((secretKey[secretKey.length-1] << 2) | 0xF) ^ secretKey[0]); for (int i = 1; i < BLOCK_LENGTH; i++) iv[i] = (byte)(((secretKey[i-1] << (i%5)) | 0xF) ^ secretKey[i]); } return iv; } private int digest(byte[] input) { messageDigest.reset(); byte[] digest = messageDigest.digest(input); byte[] condenseDigest = new byte[2]; // no matter how long the digest is, condense it into an short. for (int i = 0; i < digest.length; i++) condenseDigest[i%2] ^= digest[i]; int retval = (condenseDigest[0] & 0xFF) | ((condenseDigest[1] << 8) & 0xFF00); return retval; } public SecureRandom getSecureRandom() { return new SecureRandom(mainIV); } public CipherProvider createNewCipher(int mode) throws StandardException { return createNewCipher(mode, mainSecretKey, mainIV); } private CipherProvider createNewCipher(int mode, SecretKey secretKey, byte[] iv) throws StandardException { return new JCECipherProvider(mode, secretKey, iv, cryptoAlgorithm, cryptoProviderShort); } /* * module control methods */ public void boot(boolean create, Properties properties) throws StandardException { boolean provider_or_algo_specified = false; boolean storeProperties = create; String externalKey = properties.getProperty(Attribute.CRYPTO_EXTERNAL_KEY); if (externalKey != null) { storeProperties = false; } cryptoProvider = properties.getProperty(Attribute.CRYPTO_PROVIDER); if (cryptoProvider == null) { // JDK 1.3 does not create providers by itself. if (JVMInfo.JDK_ID == JVMInfo.J2SE_13) { String vendor; try { vendor = System.getProperty("java.vendor", ""); } catch (SecurityException se) { vendor = ""; } vendor = StringUtil.SQLToUpperCase(vendor); if (vendor.startsWith("IBM ")) cryptoProvider = "com.ibm.crypto.provider.IBMJCE"; else if (vendor.startsWith("SUN ")) cryptoProvider = "com.sun.crypto.provider.SunJCE"; } } else { provider_or_algo_specified = true; // explictly putting the properties back into the properties // saves then in service.properties at create time. // if (storeProperties) // properties.put(Attribute.CRYPTO_PROVIDER, cryptoProvider); int dotPos = cryptoProvider.lastIndexOf('.'); if (dotPos == -1) cryptoProviderShort = cryptoProvider; else cryptoProviderShort = cryptoProvider.substring(dotPos+1); } cryptoAlgorithm = properties.getProperty(Attribute.CRYPTO_ALGORITHM); if (cryptoAlgorithm == null) cryptoAlgorithm = DEFAULT_ALGORITHM; else { provider_or_algo_specified = true; } // explictly putting the properties back into the properties // saves then in service.properties at create time. if (storeProperties) properties.put(Attribute.CRYPTO_ALGORITHM, cryptoAlgorithm); int firstSlashPos = cryptoAlgorithm.indexOf('/'); int lastSlashPos = cryptoAlgorithm.lastIndexOf('/'); if (firstSlashPos < 0 || lastSlashPos < 0 || firstSlashPos == lastSlashPos) throw StandardException.newException(SQLState.ENCRYPTION_BAD_ALG_FORMAT, cryptoAlgorithm); cryptoAlgorithmShort = cryptoAlgorithm.substring(0,firstSlashPos); if (provider_or_algo_specified) { // Track 3715 - disable use of provider/aglo specification if // jce environment is not 1.2.1. The ExemptionMechanism class // exists in jce1.2.1 and not in jce1.2, so try and load the // class and if you can't find it don't allow the encryption. // This is a requirement from the government to give cloudscape // export clearance for 3.6. Note that the check is not needed // if no provider/algo is specified, in that case we default to // a DES weak encryption algorithm which also is allowed for // export (this is how 3.5 got it's clearance). try { Class c = Class.forName("javax.crypto.ExemptionMechanism"); } catch (Throwable t) { throw StandardException.newException( SQLState.ENCRYPTION_BAD_JCE); } } // If connecting to an existing database and Attribute.CRYPTO_KEY_LENGTH is set // then obtain the encoded key length values without padding bytes and retrieve // the keylength in bits if boot password mechanism is used // note: Attribute.CRYPTO_KEY_LENGTH is set during creation time to a supported // key length in the connection url. Internally , two values are stored in this property // if encryptionKey is used, this property will have only the encoded key length // if boot password mechanism is used, this property will have the following // keylengthBits-EncodedKeyLength if(!create) { // if available, parse the keylengths stored in Attribute.CRYPTO_KEY_LENGTH if(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH) != null) { String keyLengths = properties.getProperty(Attribute.CRYPTO_KEY_LENGTH); int pos = keyLengths.lastIndexOf('-'); encodedKeyLength = Integer.parseInt(keyLengths.substring(pos+1)); if(pos != -1) keyLengthBits = Integer.parseInt(keyLengths.substring(0,pos)); } } // case 1 - if 'encryptionKey' is not set and 'encryptionKeyLength' is set, then use // the 'encryptionKeyLength' property value as the keyLength in bits. // case 2 - 'encryptionKey' property is not set and 'encryptionKeyLength' is not set, then // use the defaults keylength: 56bits for DES, 168 for DESede and 128 for any other encryption // algorithm if (externalKey == null && create) { if(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH) != null) { keyLengthBits = Integer.parseInt(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH)); } else if (cryptoAlgorithmShort.equals(DES)) { keyLengthBits = 56; } else if (cryptoAlgorithmShort.equals(DESede) || cryptoAlgorithmShort.equals(TripleDES)) { keyLengthBits = 168; } else { keyLengthBits = 128; } } // check the feedback mode String feedbackMode = cryptoAlgorithm.substring(firstSlashPos+1,lastSlashPos); if (!feedbackMode.equals("CBC") && !feedbackMode.equals("CFB") && !feedbackMode.equals("ECB") && !feedbackMode.equals("OFB")) throw StandardException.newException(SQLState.ENCRYPTION_BAD_FEEDBACKMODE, feedbackMode); // check the NoPadding mode is used String padding = cryptoAlgorithm.substring(lastSlashPos+1,cryptoAlgorithm.length()); if (!padding.equals("NoPadding")) throw StandardException.newException(SQLState.ENCRYPTION_BAD_PADDING, padding); Throwable t; try { if (cryptoProvider != null) { // provider package should be set by property if (Security.getProvider(cryptoProviderShort) == null) { action = 1; // add provider through privileged block. java.security.AccessController.doPrivileged(this); } } // need this to check the boot password messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST); byte[] generatedKey; if (externalKey != null) { // incorrect to specify external key and boot password if (properties.getProperty(Attribute.BOOT_PASSWORD) != null) throw StandardException.newException(SQLState.SERVICE_WRONG_BOOT_PASSWORD); generatedKey = org.apache.derby.iapi.util.StringUtil.fromHexString(externalKey, 0, externalKey.length()); if (generatedKey == null) { throw StandardException.newException( // If length is even, we assume invalid character(s), // based on how 'fromHexString' behaves. externalKey.length() % 2 == 0 ? SQLState.ENCRYPTION_ILLEGAL_EXKEY_CHARS : SQLState.ENCRYPTION_INVALID_EXKEY_LENGTH); } } else { generatedKey = handleBootPassword(create, properties); if(create) properties.put(Attribute.CRYPTO_KEY_LENGTH,keyLengthBits+"-"+generatedKey.length); } // Make a key and IV object out of the generated key mainSecretKey = generateKey(generatedKey); mainIV = generateIV(generatedKey); if (create) { properties.put(Attribute.DATA_ENCRYPTION, "true"); // Set two new properties to allow for future changes to the log and data encryption // schemes. This property is introduced in version 10 , value starts at 1. properties.put(RawStoreFactory.DATA_ENCRYPT_ALGORITHM_VERSION,String.valueOf(1)); properties.put(RawStoreFactory.LOG_ENCRYPT_ALGORITHM_VERSION,String.valueOf(1)); } return; } catch (java.security.PrivilegedActionException pae) { t = pae.getException(); } catch (NoSuchAlgorithmException nsae) { t = nsae; } catch (SecurityException se) { t = se; } catch (LinkageError le) { t = le; } catch (ClassCastException cce) { t = cce; } throw StandardException.newException(SQLState.MISSING_ENCRYPTION_PROVIDER, t); } private byte[] handleBootPassword(boolean create, Properties properties) throws StandardException { String inputKey = properties.getProperty(Attribute.BOOT_PASSWORD); if (inputKey == null) { throw StandardException.newException(SQLState.SERVICE_WRONG_BOOT_PASSWORD); } byte[] bootPassword = StringUtil.getAsciiBytes(inputKey); if (bootPassword.length < CipherFactory.MIN_BOOTPASS_LENGTH) { String messageId = create ? SQLState.SERVICE_BOOT_PASSWORD_TOO_SHORT : SQLState.SERVICE_WRONG_BOOT_PASSWORD; throw StandardException.newException(messageId); } // Each database has its own unique encryption key that is // not known even to the user. However, this key is masked // with the user input key and stored in the // services.properties file so that, with the user key, the // encryption key can easily be recovered. // To change the user encryption key to a database, simply // recover the unique real encryption key and masked it // with the new user key. byte[] generatedKey; if (create) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -