1 21 22 package org.apache.derby.impl.services.jce; 23 24 import org.apache.derby.iapi.services.crypto.CipherFactory; 25 import org.apache.derby.iapi.services.crypto.CipherProvider; 26 27 import org.apache.derby.iapi.services.monitor.Monitor; 28 import org.apache.derby.iapi.services.sanity.SanityManager; 29 30 import org.apache.derby.iapi.error.StandardException; 31 32 import org.apache.derby.iapi.services.info.JVMInfo; 33 import org.apache.derby.iapi.util.StringUtil; 34 35 import org.apache.derby.iapi.reference.SQLState; 36 import org.apache.derby.iapi.reference.Attribute; 37 import org.apache.derby.iapi.util.StringUtil; 38 39 import java.util.Properties ; 40 import java.util.Enumeration ; 41 import java.security.Key ; 42 import java.security.Provider ; 43 import java.security.SecureRandom ; 44 import java.security.Security ; 45 import java.security.InvalidKeyException ; 46 import java.security.NoSuchAlgorithmException ; 47 import java.security.MessageDigest ; 48 import java.security.spec.KeySpec ; 49 import java.security.spec.InvalidKeySpecException ; 50 import java.io.FileNotFoundException ; 51 import java.io.IOException ; 52 import java.io.InputStream ; 53 import java.io.DataInputStream ; 54 55 import javax.crypto.KeyGenerator; 56 import javax.crypto.SecretKey; 57 import javax.crypto.SecretKeyFactory; 58 import javax.crypto.spec.DESKeySpec; 59 import javax.crypto.spec.SecretKeySpec; 60 import org.apache.derby.iapi.store.raw.RawStoreFactory; 61 62 import org.apache.derby.io.StorageFactory; 63 import org.apache.derby.io.WritableStorageFactory; 64 import org.apache.derby.io.StorageFile; 65 import org.apache.derby.io.StorageRandomAccessFile; 66 71 public final class JCECipherFactory implements CipherFactory, java.security.PrivilegedExceptionAction 72 { 73 private final static String MESSAGE_DIGEST = "MD5"; 74 75 private final static String DEFAULT_PROVIDER = "com.sun.crypto.provider.SunJCE"; 76 private final static String DEFAULT_ALGORITHM = "DES/CBC/NoPadding"; 77 private final static String DES = "DES"; 78 private final static String DESede = "DESede"; 79 private final static String TripleDES = "TripleDES"; 80 private final static String AES = "AES"; 81 82 private final static int BLOCK_LENGTH = 8; 84 85 90 private final static int AES_IV_LENGTH = 16; 91 92 private int keyLengthBits; 94 private int encodedKeyLength; 95 private String cryptoAlgorithm; 96 private String cryptoAlgorithmShort; 97 private String cryptoProvider; 98 private String cryptoProviderShort; 99 private MessageDigest messageDigest; 100 101 private SecretKey mainSecretKey; 102 private byte[] mainIV; 103 104 private Properties persistentProperties; 107 108 109 113 private final static int VERIFYKEY_DATALEN = 4096; 114 private StorageFile activeFile; 115 private int action; 116 private String activePerms; 117 118 119 131 public JCECipherFactory(boolean create, 132 Properties props, 133 boolean newAttributes) 134 throws StandardException 135 { 136 init(create, props, newAttributes); 137 } 138 139 140 141 static String providerErrorName(String cps) { 142 143 return cps == null ? "default" : cps; 144 } 145 146 147 private byte[] generateUniqueBytes() throws StandardException 148 { 149 try { 150 151 String provider = cryptoProviderShort; 152 153 KeyGenerator keyGen; 154 if (provider == null) 155 { 156 keyGen = KeyGenerator.getInstance(cryptoAlgorithmShort); 157 } 158 else 159 { 160 if( provider.equals("BouncyCastleProvider")) 161 provider = "BC"; 162 keyGen = KeyGenerator.getInstance(cryptoAlgorithmShort, provider); 163 } 164 165 keyGen.init(keyLengthBits); 166 167 SecretKey key = keyGen.generateKey(); 168 169 return key.getEncoded(); 170 171 } catch (java.security.NoSuchAlgorithmException nsae) { 172 throw StandardException.newException(SQLState.ENCRYPTION_NOSUCH_ALGORITHM, cryptoAlgorithm, 173 JCECipherFactory.providerErrorName(cryptoProviderShort)); 174 } catch (java.security.NoSuchProviderException nspe) { 175 throw StandardException.newException(SQLState.ENCRYPTION_BAD_PROVIDER, 176 JCECipherFactory.providerErrorName(cryptoProviderShort)); 177 } 178 } 179 180 191 private String encryptKey(byte[] secretKey, byte[] bootPassword) 192 throws StandardException 193 { 194 198 int muckLength = secretKey.length; 199 if(cryptoAlgorithmShort.equals(AES)) 200 muckLength = AES_IV_LENGTH; 201 202 byte[] muck = getMuckFromBootPassword(bootPassword, muckLength); 203 SecretKey key = generateKey(muck); 204 byte[] IV = generateIV(muck); 205 CipherProvider tmpCipherProvider = createNewCipher(ENCRYPT,key,IV); 206 207 encodedKeyLength = secretKey.length; 209 210 secretKey = padKey(secretKey,tmpCipherProvider.getEncryptionBlockSize()); 213 214 byte[] result = new byte[secretKey.length]; 215 216 tmpCipherProvider.encrypt(secretKey, 0, secretKey.length, result, 0); 218 219 return org.apache.derby.iapi.util.StringUtil.toHexString(result, 0, result.length); 220 221 } 222 223 232 private byte[] padKey(byte[] secretKey,int blockSizeAlign) 233 { 234 byte [] result = secretKey; 235 if(secretKey.length % blockSizeAlign != 0 ) 236 { 237 int encryptedLength = secretKey.length + blockSizeAlign - (secretKey.length % blockSizeAlign); 238 result = new byte[encryptedLength]; 239 System.arraycopy(secretKey,0,result,0,secretKey.length); 240 } 241 return result; 242 } 243 244 252 private byte[] decryptKey(String encryptedKey, int encodedKeyCharLength, byte[] bootPassword) 253 throws StandardException 254 { 255 byte[] secretKey = org.apache.derby.iapi.util.StringUtil.fromHexString(encryptedKey, 0, encodedKeyCharLength); 256 int muckLength; 260 if(cryptoAlgorithmShort.equals(AES)) 261 muckLength = AES_IV_LENGTH; 262 else 263 muckLength = secretKey.length; 264 265 byte[] muck = getMuckFromBootPassword(bootPassword, muckLength); 266 267 268 SecretKey key = generateKey(muck); 271 byte[] IV = generateIV(muck); 272 273 274 createNewCipher(DECRYPT, key, IV). 275 decrypt(secretKey, 0, secretKey.length, secretKey, 0); 276 277 return secretKey; 278 } 279 280 private byte[] getMuckFromBootPassword(byte[] bootPassword, int encodedKeyByteLength) { 281 int ulength = bootPassword.length; 282 283 byte[] muck = new byte[encodedKeyByteLength]; 284 285 286 int rotation = 0; 287 for (int i = 0; i < bootPassword.length; i++) 288 rotation += bootPassword[i]; 289 290 for (int i = 0; i < encodedKeyByteLength; i++) 291 muck[i] = (byte)(bootPassword[(i+rotation)%ulength] ^ 292 (bootPassword[i%ulength] << 4)); 293 294 return muck; 295 } 296 297 303 private SecretKey generateKey(byte[] secretKey) throws StandardException 304 { 305 int length = secretKey.length; 306 307 if (length < CipherFactory.MIN_BOOTPASS_LENGTH) 308 throw StandardException.newException(SQLState.ILLEGAL_BP_LENGTH, new Integer (MIN_BOOTPASS_LENGTH)); 309 310 try 311 { 312 if (cryptoAlgorithmShort.equals(DES)) 313 { if (DESKeySpec.isWeak(secretKey, 0)) 315 { 316 byte[] spice = StringUtil.getAsciiBytes("louDScap"); 318 for (int i = 0; i < 7; i++) 319 secretKey[i] = (byte)((spice[i] << 3) ^ secretKey[i]); 320 } 321 } 322 return new SecretKeySpec(secretKey, cryptoAlgorithmShort); 323 } 324 catch (InvalidKeyException ike) 325 { 326 throw StandardException.newException(SQLState.CRYPTO_EXCEPTION, ike); 327 } 328 329 } 330 331 335 private byte[] generateIV(byte[] secretKey) 336 { 337 338 int IVlen = BLOCK_LENGTH; 342 343 byte[] iv = null; 344 if(cryptoAlgorithmShort.equals(AES)) 345 { 346 IVlen = AES_IV_LENGTH; 347 iv = new byte[IVlen]; 348 iv[0] = (byte)(((secretKey[secretKey.length-1] << 2) | 0xF) ^ secretKey[0]); 349 for (int i = 1; i < BLOCK_LENGTH; i++) 350 iv[i] = (byte)(((secretKey[i-1] << (i%5)) | 0xF) ^ secretKey[i]); 351 352 for(int i = BLOCK_LENGTH ; i < AES_IV_LENGTH ; i++) 353 { 354 iv[i]=iv[i-BLOCK_LENGTH]; 355 } 356 357 } 358 else 359 { 360 iv = new byte[BLOCK_LENGTH]; 361 iv[0] = (byte)(((secretKey[secretKey.length-1] << 2) | 0xF) ^ secretKey[0]); 362 for (int i = 1; i < BLOCK_LENGTH; i++) 363 iv[i] = (byte)(((secretKey[i-1] << (i%5)) | 0xF) ^ secretKey[i]); 364 } 365 366 return iv; 367 } 368 369 private int digest(byte[] input) 370 { 371 messageDigest.reset(); 372 byte[] digest = messageDigest.digest(input); 373 byte[] condenseDigest = new byte[2]; 374 375 for (int i = 0; i < digest.length; i++) 377 condenseDigest[i%2] ^= digest[i]; 378 379 int retval = (condenseDigest[0] & 0xFF) | ((condenseDigest[1] << 8) & 0xFF00); 380 381 return retval; 382 } 383 384 public SecureRandom getSecureRandom() { 385 return new SecureRandom (mainIV); 386 } 387 388 public CipherProvider createNewCipher(int mode) 389 throws StandardException { 390 return createNewCipher(mode, mainSecretKey, mainIV); 391 } 392 393 394 private CipherProvider createNewCipher(int mode, SecretKey secretKey, 395 byte[] iv) 396 throws StandardException 397 { 398 return new JCECipherProvider(mode, secretKey, iv, cryptoAlgorithm, cryptoProviderShort); 399 } 400 401 402 405 public void init(boolean create, Properties properties, boolean newAttrs) 406 throws StandardException 407 { 408 409 boolean provider_or_algo_specified = false; 410 boolean storeProperties = create; 411 persistentProperties = new Properties (); 412 413 String externalKey = properties.getProperty((newAttrs ? 418 Attribute.NEW_CRYPTO_EXTERNAL_KEY: 419 Attribute.CRYPTO_EXTERNAL_KEY)); 420 if (externalKey != null) { 421 storeProperties = false; 422 } 423 424 cryptoProvider = properties.getProperty(Attribute.CRYPTO_PROVIDER); 425 426 if (cryptoProvider == null) 427 { 428 if (JVMInfo.JDK_ID == JVMInfo.J2SE_13) { 430 431 String vendor; 432 try { 433 vendor = System.getProperty("java.vendor", ""); 434 } catch (SecurityException se) { 435 vendor = ""; 436 } 437 438 vendor = StringUtil.SQLToUpperCase(vendor); 439 440 if (vendor.startsWith("IBM ")) 441 cryptoProvider = "com.ibm.crypto.provider.IBMJCE"; 442 else if (vendor.startsWith("SUN ")) 443 cryptoProvider = "com.sun.crypto.provider.SunJCE"; 444 445 } 446 } 447 else 448 { 449 provider_or_algo_specified = true; 450 451 456 int dotPos = cryptoProvider.lastIndexOf('.'); 457 if (dotPos == -1) 458 cryptoProviderShort = cryptoProvider; 459 else 460 cryptoProviderShort = cryptoProvider.substring(dotPos+1); 461 462 } 463 464 cryptoAlgorithm = properties.getProperty(Attribute.CRYPTO_ALGORITHM); 465 if (cryptoAlgorithm == null) 466 cryptoAlgorithm = DEFAULT_ALGORITHM; 467 else { 468 provider_or_algo_specified = true; 469 470 } 471 472 if (storeProperties) 475 persistentProperties.put(Attribute.CRYPTO_ALGORITHM, 476 cryptoAlgorithm); 477 478 int firstSlashPos = cryptoAlgorithm.indexOf('/'); 479 int lastSlashPos = cryptoAlgorithm.lastIndexOf('/'); 480 if (firstSlashPos < 0 || lastSlashPos < 0 || firstSlashPos == lastSlashPos) 481 throw StandardException.newException(SQLState.ENCRYPTION_BAD_ALG_FORMAT, cryptoAlgorithm); 482 483 cryptoAlgorithmShort = cryptoAlgorithm.substring(0,firstSlashPos); 484 485 if (provider_or_algo_specified) 486 { 487 try 497 { 498 Class c = Class.forName("javax.crypto.ExemptionMechanism"); 499 } 500 catch (Throwable t) 501 { 502 throw StandardException.newException( 503 SQLState.ENCRYPTION_BAD_JCE); 504 } 505 } 506 507 516 if(!create) 517 { 518 if(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH) != null) 520 { 521 String keyLengths = properties.getProperty(Attribute.CRYPTO_KEY_LENGTH); 522 int pos = keyLengths.lastIndexOf('-'); 523 encodedKeyLength = Integer.parseInt(keyLengths.substring(pos+1)); 524 if(pos != -1) 525 keyLengthBits = Integer.parseInt(keyLengths.substring(0,pos)); 526 } 527 } 528 529 530 536 if (externalKey == null && create) { 537 if(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH) != null) 538 { 539 keyLengthBits = Integer.parseInt(properties.getProperty(Attribute.CRYPTO_KEY_LENGTH)); 540 } 541 else if (cryptoAlgorithmShort.equals(DES)) { 542 keyLengthBits = 56; 543 } else if (cryptoAlgorithmShort.equals(DESede) || cryptoAlgorithmShort.equals(TripleDES)) { 544 keyLengthBits = 168; 545 546 } else { 547 keyLengthBits = 128; 548 } 549 } 550 551 String feedbackMode = cryptoAlgorithm.substring(firstSlashPos+1,lastSlashPos); 553 554 if (!feedbackMode.equals("CBC") && !feedbackMode.equals("CFB") && 555 !feedbackMode.equals("ECB") && !feedbackMode.equals("OFB")) 556 throw StandardException.newException(SQLState.ENCRYPTION_BAD_FEEDBACKMODE, feedbackMode); 557 558 String padding = cryptoAlgorithm.substring(lastSlashPos+1,cryptoAlgorithm.length()); 560 if (!padding.equals("NoPadding")) 561 throw StandardException.newException(SQLState.ENCRYPTION_BAD_PADDING, padding); 562 563 Throwable t; 564 try 565 { 566 if (cryptoProvider != null) { 567 if (Security.getProvider(cryptoProviderShort) == null) 569 { 570 action = 1; 571 java.security.AccessController.doPrivileged(this); 573 } 574 } 575 576 messageDigest = MessageDigest.getInstance(MESSAGE_DIGEST); 578 579 byte[] generatedKey; 580 if (externalKey != null) { 581 582 if (properties.getProperty((newAttrs ? 584 Attribute.NEW_BOOT_PASSWORD : 585 Attribute.BOOT_PASSWORD)) != null) 586 throw StandardException.newException(SQLState.SERVICE_WRONG_BOOT_PASSWORD); 587 588 generatedKey = 589 org.apache.derby.iapi.util.StringUtil.fromHexString(externalKey, 590 0, 591 externalKey.length()); 592 if (generatedKey == null) { 593 throw StandardException.newException( 594 externalKey.length() % 2 == 0 597 ? SQLState.ENCRYPTION_ILLEGAL_EXKEY_CHARS 598 : SQLState.ENCRYPTION_INVALID_EXKEY_LENGTH); 599 } 600 601 } else { 602 603 generatedKey = handleBootPassword(create, properties, newAttrs); 604 if(create || newAttrs) 605 persistentProperties.put(Attribute.CRYPTO_KEY_LENGTH, 606 keyLengthBits+"-"+generatedKey.length); 607 } 608 609 mainSecretKey = generateKey(generatedKey); 611 mainIV = generateIV(generatedKey); 612 613 if (create) 614 { 615 persistentProperties.put(Attribute.DATA_ENCRYPTION, "true"); 616 617 persistentProperties.put(RawStoreFactory.DATA_ENCRYPT_ALGORITHM_VERSION, 620 String.valueOf(1)); 621 persistentProperties.put(RawStoreFactory.LOG_ENCRYPT_ALGORITHM_VERSION, 622 String.valueOf(1)); 623 } 624 625 return; 626 } 627 catch (java.security.PrivilegedActionException pae) 628 { 629 t = pae.getException(); 630 } 631 catch (NoSuchAlgorithmException nsae) 632 { 633 t = nsae; 634 } 635 catch (SecurityException se) 636 { 637 t = se; 638 } catch (LinkageError le) { 639 t = le; 640 } catch (ClassCastException cce) { 641 t = cce; 642 } 643 644 throw StandardException.newException(SQLState.MISSING_ENCRYPTION_PROVIDER, t); 645 } 646 647 648 private byte[] handleBootPassword(boolean create, 649 Properties properties, 650 boolean newPasswd) 651 throws StandardException { 652 653 654 String inputKey = properties.getProperty((newPasswd ? 657 Attribute.NEW_BOOT_PASSWORD : 658 Attribute.BOOT_PASSWORD)); 659 if (inputKey == null) 660 { 661 throw StandardException.newException(SQLState.SERVICE_WRONG_BOOT_PASSWORD); 662 } 663 664 byte[] bootPassword = StringUtil.getAsciiBytes(inputKey); 665 666 if (bootPassword.length < CipherFactory.MIN_BOOTPASS_LENGTH) 667 { 668 String messageId = create ? SQLState.SERVICE_BOOT_PASSWORD_TOO_SHORT : 669 SQLState.SERVICE_WRONG_BOOT_PASSWORD; 670 671 throw StandardException.newException(messageId); 672 } 673 674 683 byte[] generatedKey; 684 685 if (create || newPasswd) 686 { 687 generatedKey = generateUniqueBytes(); 689 690 persistentProperties.put(RawStoreFactory.ENCRYPTED_KEY, 691 saveSecretKey(generatedKey, bootPassword)); 692 693 } 694 else 695 { 696 generatedKey = getDatabaseSecretKey(properties, bootPassword, SQLState.SERVICE_WRONG_BOOT_PASSWORD); 697 } 698 699 return generatedKey; 700 } 701 702 708 public void saveProperties(Properties properties) 709 { 710 for (Enumeration e = persistentProperties.keys(); 713 e.hasMoreElements(); ) 714 { 715 String key = (String ) e.nextElement(); 716 properties.put(key, persistentProperties.get(key)); 717 } 718 719 persistentProperties = null; 721 } 722 723 724 737 private byte[] getDatabaseSecretKey(Properties properties, byte[] bootPassword, String errorState) throws StandardException { 738 739 String keyString = properties.getProperty(RawStoreFactory.ENCRYPTED_KEY); 742 if (keyString == null) 743 throw StandardException.newException(errorState); 744 745 int encodedKeyCharLength = keyString.indexOf('-'); 746 747 if (encodedKeyCharLength == -1) throw StandardException.newException(errorState); 749 750 int verifyKey = Integer.parseInt(keyString.substring(encodedKeyCharLength+1)); 751 byte[] generatedKey = decryptKey(keyString, encodedKeyCharLength, bootPassword); 752 753 int checkKey = digest(generatedKey); 754 755 if (checkKey != verifyKey) 756 throw StandardException.newException(errorState); 757 758 byte[] result; 761 if(encodedKeyLength != 0) 762 { 763 result = new byte[encodedKeyLength]; 764 765 System.arraycopy(generatedKey,0,result,0,encodedKeyLength); 767 return result; 768 } 769 770 return generatedKey; 771 } 772 773 private String saveSecretKey(byte[] secretKey, byte[] bootPassword) throws StandardException { 774 String encryptedKey = encryptKey(secretKey, bootPassword); 775 776 int verifyKey = digest(secretKey); 779 780 return encryptedKey.concat("-" + verifyKey); 781 782 } 783 784 public String changeBootPassword(String changeString, Properties properties, CipherProvider verify) 785 throws StandardException { 786 787 int seperator = changeString.indexOf(','); 790 if (seperator == -1) 791 throw StandardException.newException(SQLState.WRONG_PASSWORD_CHANGE_FORMAT); 792 793 String oldBP = changeString.substring(0, seperator).trim(); 794 byte[] oldBPAscii = StringUtil.getAsciiBytes(oldBP); 795 if (oldBPAscii == null || oldBPAscii.length < CipherFactory.MIN_BOOTPASS_LENGTH) 796 throw StandardException.newException(SQLState.WRONG_BOOT_PASSWORD);; 797 798 String newBP = changeString.substring(seperator+1).trim(); 799 byte[] newBPAscii = StringUtil.getAsciiBytes(newBP); 800 if (newBPAscii == null || newBPAscii.length < CipherFactory.MIN_BOOTPASS_LENGTH) 801 throw StandardException.newException(SQLState.ILLEGAL_BP_LENGTH, 802 new Integer (CipherFactory.MIN_BOOTPASS_LENGTH)); 803 804 806 byte[] generatedKey = getDatabaseSecretKey(properties, oldBPAscii, SQLState.WRONG_BOOT_PASSWORD); 807 808 byte[] IV = generateIV(generatedKey); 810 811 if (!((JCECipherProvider) verify).verifyIV(IV)) 812 throw StandardException.newException(SQLState.WRONG_BOOT_PASSWORD); 813 814 815 String newkey = saveSecretKey(generatedKey, newBPAscii); 818 819 properties.put(Attribute.CRYPTO_KEY_LENGTH,keyLengthBits+"-"+encodedKeyLength); 820 821 822 return saveSecretKey(generatedKey, newBPAscii); 823 } 824 825 828 public final Object run() throws StandardException, InstantiationException , IllegalAccessException { 829 830 try { 831 832 switch(action) 833 { 834 case 1: 835 Security.addProvider( 836 (Provider)(Class.forName(cryptoProvider).newInstance())); 837 break; 838 case 2: 839 return activeFile.getRandomAccessFile(activePerms); 842 case 3: 843 return activeFile.getInputStream(); 844 845 } 846 847 } catch (ClassNotFoundException cnfe) { 848 throw StandardException.newException(SQLState.ENCRYPTION_NO_PROVIDER_CLASS,cryptoProvider); 849 } 850 catch(FileNotFoundException fnfe) { 851 throw StandardException.newException(SQLState.ENCRYPTION_UNABLE_KEY_VERIFICATION,cryptoProvider); 852 } 853 return null; 854 } 855 856 857 858 888 889 public void verifyKey(boolean create, StorageFactory sf, Properties properties) 890 throws StandardException 891 { 892 893 if(properties.getProperty(Attribute.CRYPTO_EXTERNAL_KEY) == null) 894 return; 895 896 902 InputStream verifyKeyInputStream = null; 903 StorageRandomAccessFile verifyKeyFile = null; 904 byte[] data = new byte[VERIFYKEY_DATALEN]; 905 try 906 { 907 if(create) 908 { 909 getSecureRandom().nextBytes(data); 910 byte[] checksum = getMD5Checksum(data); 912 913 CipherProvider tmpCipherProvider = createNewCipher(ENCRYPT,mainSecretKey,mainIV); 914 tmpCipherProvider.encrypt(data, 0, data.length, data, 0); 915 verifyKeyFile = privAccessFile(sf,Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE,"rw"); 917 verifyKeyFile.writeInt(checksum.length); 919 verifyKeyFile.write(checksum); 920 verifyKeyFile.write(data); 921 verifyKeyFile.sync(true); 922 } 923 else 924 { 925 verifyKeyInputStream = privAccessGetInputStream(sf,Attribute.CRYPTO_EXTERNAL_KEY_VERIFY_FILE); 929 DataInputStream dis = new DataInputStream (verifyKeyInputStream); 930 int checksumLen = dis.readInt(); 932 933 byte[] originalChecksum = new byte[checksumLen]; 934 dis.readFully(originalChecksum); 935 936 dis.readFully(data); 937 938 CipherProvider tmpCipherProvider = createNewCipher(DECRYPT,mainSecretKey,mainIV); 940 tmpCipherProvider.decrypt(data, 0, data.length, data, 0); 941 942 byte[] verifyChecksum = getMD5Checksum(data); 943 944 if(!MessageDigest.isEqual(originalChecksum,verifyChecksum)) 945 { 946 throw StandardException.newException(SQLState.ENCRYPTION_BAD_EXTERNAL_KEY); 947 } 948 949 } 950 } 951 catch(IOException ioe) 952 { 953 throw StandardException.newException(SQLState.ENCRYPTION_UNABLE_KEY_VERIFICATION,ioe); 954 } 955 finally 956 { 957 try 958 { 959 if(verifyKeyFile != null) 960 verifyKeyFile.close(); 961 if (verifyKeyInputStream != null ) 962 verifyKeyInputStream.close(); 963 } 964 catch(IOException ioee) 965 { 966 throw StandardException.newException(SQLState.ENCRYPTION_UNABLE_KEY_VERIFICATION,ioee); 967 } 968 } 969 return ; 970 } 971 972 973 979 private byte[] getMD5Checksum(byte[] data) 980 throws StandardException 981 { 982 try 983 { 984 MessageDigest md5 = MessageDigest.getInstance("MD5"); 986 return md5.digest(data); 987 } 988 catch(NoSuchAlgorithmException nsae) 989 { 990 throw StandardException.newException(SQLState.ENCRYPTION_BAD_ALG_FORMAT,MESSAGE_DIGEST); 991 } 992 993 } 994 995 996 1006 private StorageRandomAccessFile privAccessFile(StorageFactory storageFactory,String fileName,String filePerms) 1007 throws java.io.IOException 1008 { 1009 StorageFile verifyKeyFile = storageFactory.newStorageFile("",fileName); 1010 activeFile = verifyKeyFile; 1011 this.action = 2; 1012 activePerms = filePerms; 1013 try 1014 { 1015 return (StorageRandomAccessFile)java.security.AccessController.doPrivileged(this); 1016 } 1017 catch( java.security.PrivilegedActionException pae) 1018 { 1019 throw (java.io.IOException )pae.getException(); 1020 } 1021 } 1022 1023 1030 private InputStream privAccessGetInputStream(StorageFactory storageFactory,String fileName) 1031 throws StandardException 1032 { 1033 StorageFile verifyKeyFile = storageFactory.newStorageFile("",fileName); 1034 activeFile = verifyKeyFile; 1035 this.action = 3; 1036 try 1037 { 1038 return (InputStream )java.security.AccessController.doPrivileged(this); 1039 } 1040 catch( java.security.PrivilegedActionException pae) 1041 { 1042 throw (StandardException)pae.getException(); 1043 } 1044 } 1045 1046} 1047 | Popular Tags |