1 25 package org.ofbiz.accounting.thirdparty.valuelink; 26 27 import java.math.BigInteger ; 28 import java.security.InvalidAlgorithmParameterException ; 29 import java.security.InvalidKeyException ; 30 import java.security.KeyFactory ; 31 import java.security.KeyPair ; 32 import java.security.KeyPairGenerator ; 33 import java.security.MessageDigest ; 34 import java.security.NoSuchAlgorithmException ; 35 import java.security.PrivateKey ; 36 import java.security.PublicKey ; 37 import java.security.spec.InvalidKeySpecException ; 38 import java.text.DecimalFormat ; 39 import java.text.ParseException ; 40 import java.text.SimpleDateFormat ; 41 import java.util.ArrayList ; 42 import java.util.Date ; 43 import java.util.HashMap ; 44 import java.util.List ; 45 import java.util.Map ; 46 import java.util.Properties ; 47 import java.util.Random ; 48 49 import javax.crypto.BadPaddingException; 50 import javax.crypto.Cipher; 51 import javax.crypto.IllegalBlockSizeException; 52 import javax.crypto.KeyAgreement; 53 import javax.crypto.KeyGenerator; 54 import javax.crypto.NoSuchPaddingException; 55 import javax.crypto.SecretKey; 56 import javax.crypto.SecretKeyFactory; 57 import javax.crypto.interfaces.DHPrivateKey; 58 import javax.crypto.interfaces.DHPublicKey; 59 import javax.crypto.spec.DESKeySpec; 60 import javax.crypto.spec.DESedeKeySpec; 61 import javax.crypto.spec.DHParameterSpec; 62 import javax.crypto.spec.DHPrivateKeySpec; 63 import javax.crypto.spec.DHPublicKeySpec; 64 import javax.crypto.spec.IvParameterSpec; 65 66 import org.ofbiz.base.util.Debug; 67 import org.ofbiz.base.util.HttpClient; 68 import org.ofbiz.base.util.HttpClientException; 69 import org.ofbiz.base.util.StringUtil; 70 import org.ofbiz.base.util.UtilMisc; 71 import org.ofbiz.base.util.UtilProperties; 72 import org.ofbiz.entity.GenericDelegator; 73 import org.ofbiz.entity.GenericEntityException; 74 import org.ofbiz.entity.GenericValue; 75 76 83 public class ValueLinkApi { 84 85 public static final String module = ValueLinkApi.class.getName(); 86 87 private static Map objectCache = new HashMap (); 89 90 protected GenericDelegator delegator = null; 92 protected Properties props = null; 93 protected SecretKey kek = null; 94 protected SecretKey mwk = null; 95 protected String merchantId = null; 96 protected String terminalId = null; 97 protected Long mwkIndex = null; 98 protected boolean debug = false; 99 100 protected ValueLinkApi() {} 101 protected ValueLinkApi(GenericDelegator delegator, Properties props) { 102 String mId = (String ) props.get("payment.valuelink.merchantId"); 103 String tId = (String ) props.get("payment.valuelink.terminalId"); 104 this.delegator = delegator; 105 this.merchantId = mId; 106 this.terminalId = tId; 107 this.props = props; 108 if ("Y".equalsIgnoreCase((String ) props.get("payment.valuelink.debug"))) { 109 this.debug = true; 110 } 111 112 if (debug) { 113 Debug.log("New ValueLinkApi instance created", module); 114 Debug.log("Merchant ID : " + merchantId, module); 115 Debug.log("Terminal ID : " + terminalId, module); 116 } 117 } 118 119 126 public static ValueLinkApi getInstance(GenericDelegator delegator, Properties props, boolean reload) { 127 String merchantId = (String ) props.get("payment.valuelink.merchantId"); 128 if (props == null) { 129 throw new IllegalArgumentException ("Properties cannot be null"); 130 } 131 132 ValueLinkApi api = (ValueLinkApi) objectCache.get(merchantId); 133 if (api == null || reload) { 134 synchronized(ValueLinkApi.class) { 135 api = (ValueLinkApi) objectCache.get(merchantId); 136 if (api == null || reload) { 137 api = new ValueLinkApi(delegator, props); 138 objectCache.put(merchantId, api); 139 } 140 } 141 } 142 143 if (api == null) { 144 throw new RuntimeException ("Runtime problems with ValueLinkApi; unable to create instance"); 145 } 146 147 return api; 148 } 149 150 156 public static ValueLinkApi getInstance(GenericDelegator delegator, Properties props) { 157 return getInstance(delegator, props, false); 158 } 159 160 165 public String encryptPin(String pin) { 166 Cipher mwkCipher = this.getCipher(this.getMwkKey(), Cipher.ENCRYPT_MODE); 168 169 byte[] pinBytes = pin.getBytes(); 171 172 byte[] random = this.getRandomBytes(7); 174 175 byte[] checkSum = this.getPinCheckSum(pinBytes); 177 178 byte[] eanBlock = new byte[16]; 180 int i; 181 for (i = 0; i < random.length; i++) { 182 eanBlock[i] = random[i]; 183 } 184 eanBlock[7] = checkSum[0]; 185 for (i = 0; i < pinBytes.length; i++) { 186 eanBlock[i + 8] = pinBytes[i]; 187 } 188 189 String encryptedEanHex = null; 191 try { 192 byte[] encryptedEan = mwkCipher.doFinal(eanBlock); 193 encryptedEanHex = StringUtil.toHexString(encryptedEan); 194 } catch (IllegalStateException e) { 195 Debug.logError(e, module); 196 } catch (IllegalBlockSizeException e) { 197 Debug.logError(e, module); 198 } catch (BadPaddingException e) { 199 Debug.logError(e, module); 200 } 201 202 if (debug) { 203 Debug.log("encryptPin : " + pin + " / " + encryptedEanHex, module); 204 } 205 206 return encryptedEanHex; 207 } 208 209 214 public String decryptPin(String pin) { 215 Cipher mwkCipher = this.getCipher(this.getMwkKey(), Cipher.DECRYPT_MODE); 217 218 String decryptedPinString = null; 220 try { 221 byte[] decryptedEan = mwkCipher.doFinal(StringUtil.fromHexString(pin)); 222 byte[] decryptedPin = getByteRange(decryptedEan, 8, 8); 223 decryptedPinString = new String (decryptedPin); 224 } catch (IllegalStateException e) { 225 Debug.logError(e, module); 226 } catch (IllegalBlockSizeException e) { 227 Debug.logError(e, module); 228 } catch (BadPaddingException e) { 229 Debug.logError(e, module); 230 } 231 232 if (debug) { 233 Debug.log("decryptPin : " + pin + " / " + decryptedPinString, module); 234 } 235 236 return decryptedPinString; 237 } 238 239 245 public Map send(Map request) throws HttpClientException { 246 return send((String ) props.get("payment.valuelink.url"), request); 247 } 248 249 256 public Map send(String url, Map request) throws HttpClientException { 257 if (debug) { 258 Debug.log("Request : " + url + " / " + request, module); 259 } 260 261 String timeoutString = (String ) props.get("payment.valuelink.timeout"); 263 int timeout = 34; 264 try { 265 timeout = Integer.parseInt(timeoutString); 266 } catch (NumberFormatException e) { 267 Debug.logError(e, "Unable to set timeout to " + timeoutString + " using default " + timeout); 268 } 269 270 HttpClient client = new HttpClient(url, request); 272 client.setTimeout(timeout * 1000); 273 client.setDebug(debug); 274 275 client.setClientCertificateAlias((String ) props.get("payment.valuelink.certificateAlias")); 276 String response = client.post(); 277 278 return this.parseResponse(response); 280 } 281 282 285 public StringBuffer outputKeyCreation(boolean kekOnly, String kekTest) { 286 return this.outputKeyCreation(0, kekOnly, kekTest); 287 } 288 289 private StringBuffer outputKeyCreation(int loop, boolean kekOnly, String kekTest) { 290 StringBuffer buf = new StringBuffer (); 291 loop++; 292 293 if (loop > 100) { 294 throw new IllegalStateException ("Unable to create 128 byte keys in 100 tries"); 296 } 297 298 DHPrivateKey privateKey = null; 300 DHPublicKey publicKey = null; 301 302 if (!kekOnly) { 303 KeyPair keyPair = null; 304 try { 305 keyPair = this.createKeys(); 306 } catch (NoSuchAlgorithmException e) { 307 Debug.logError(e, module); 308 } catch (InvalidAlgorithmParameterException e) { 309 Debug.logError(e, module); 310 } catch (InvalidKeySpecException e) { 311 Debug.logError(e, module); 312 } 313 314 if (keyPair != null) { 315 publicKey = (DHPublicKey) keyPair.getPublic(); 316 privateKey = (DHPrivateKey) keyPair.getPrivate(); 317 318 if (publicKey == null || publicKey.getY().toByteArray().length != 128) { 319 return this.outputKeyCreation(loop, kekOnly, kekTest); 321 } 322 } else { 323 Debug.log("Returned a null KeyPair", module); 324 return this.outputKeyCreation(loop, kekOnly, kekTest); 325 } 326 } else { 327 try { 329 privateKey = (DHPrivateKey) this.getPrivateKey(); 330 } catch (Exception e) { 331 Debug.logError(e, module); 332 } 333 } 334 335 byte[] kekBytes = null; 337 try { 338 kekBytes = this.generateKek(privateKey); 339 } catch (NoSuchAlgorithmException e) { 340 Debug.logError(e, module); 341 } catch (InvalidKeySpecException e) { 342 Debug.logError(e, module); 343 } catch (InvalidKeyException e) { 344 Debug.logError(e, module); 345 } 346 347 SecretKey loadedKek = this.getDesEdeKey(kekBytes); 349 byte[] loadKekBytes = loadedKek.getEncoded(); 350 351 Cipher cipher = this.getCipher(this.getKekKey(), Cipher.ENCRYPT_MODE); 353 byte[] kekTestB = { 0, 0, 0, 0, 0, 0, 0, 0 }; 354 byte[] kekTestC = new byte[0]; 355 if (kekTest != null) { 356 kekTestB = StringUtil.fromHexString(kekTest); 357 } 358 359 try { 361 kekTestC = cipher.doFinal(kekTestB); 362 } catch (Exception e) { 363 Debug.logError(e, module); 364 } 365 366 if (!kekOnly) { 367 BigInteger y = publicKey.getY(); 369 byte[] yBytes = y.toByteArray(); 370 String yHex = StringUtil.toHexString(yBytes); 371 buf.append("======== Begin Public Key (Y @ " + yBytes.length + " / " + yHex.length() + ") ========\n"); 372 buf.append(yHex + "\n"); 373 buf.append("======== End Public Key ========\n\n"); 374 375 BigInteger x = privateKey.getX(); 377 byte[] xBytes = x.toByteArray(); 378 String xHex = StringUtil.toHexString(xBytes); 379 buf.append("======== Begin Private Key (X @ " + xBytes.length + " / " + xHex.length() + ") ========\n"); 380 buf.append(xHex + "\n"); 381 buf.append("======== End Private Key ========\n\n"); 382 383 byte[] privateBytes = privateKey.getEncoded(); 385 String privateHex = StringUtil.toHexString(privateBytes); 386 buf.append("======== Begin Private Key (Full @ " + privateBytes.length + " / " + privateHex.length() + ") ========\n"); 387 buf.append(privateHex + "\n"); 388 buf.append("======== End Private Key ========\n\n"); 389 } 390 391 if (kekBytes != null) { 392 buf.append("======== Begin KEK (" + kekBytes.length + ") ========\n"); 393 buf.append(StringUtil.toHexString(kekBytes) + "\n"); 394 buf.append("======== End KEK ========\n\n"); 395 396 buf.append("======== Begin KEK (DES) (" + loadKekBytes.length + ") ========\n"); 397 buf.append(StringUtil.toHexString(loadKekBytes) + "\n"); 398 buf.append("======== End KEK (DES) ========\n\n"); 399 400 buf.append("======== Begin KEK Test (" + kekTestC.length + ") ========\n"); 401 buf.append(StringUtil.toHexString(kekTestC) + "\n"); 402 buf.append("======== End KEK Test ========\n\n"); 403 } else { 404 Debug.logError("KEK came back empty", module); 405 } 406 407 return buf; 408 } 409 410 416 public KeyPair createKeys() throws NoSuchAlgorithmException , InvalidAlgorithmParameterException , InvalidKeySpecException { 417 DHPublicKey publicKey = (DHPublicKey) this.getValueLinkPublicKey(); 419 DHParameterSpec dhParamSpec = publicKey.getParams(); 420 422 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); 424 keyGen.initialize(dhParamSpec); 425 KeyPair keyPair = keyGen.generateKeyPair(); 426 427 return keyPair; 428 } 429 430 438 public byte[] generateKek(PrivateKey privateKey) throws NoSuchAlgorithmException , InvalidKeySpecException , InvalidKeyException { 439 PublicKey vlPublic = this.getValueLinkPublicKey(); 441 442 KeyAgreement ka = KeyAgreement.getInstance("DH"); 444 ka.init(privateKey); 445 ka.doPhase(vlPublic, true); 446 byte[] secretKey = ka.generateSecret(); 447 448 if (debug) { 449 Debug.log("Secret Key : " + StringUtil.toHexString(secretKey) + " / " + secretKey.length, module); 450 } 451 452 MessageDigest md = MessageDigest.getInstance("SHA1"); 454 byte[] digest = md.digest(secretKey); 455 byte[] des2 = getByteRange(digest, 0, 16); 456 byte[] first8 = getByteRange(des2, 0, 8); 457 byte[] kek = copyBytes(des2, first8, 0); 458 459 if (debug) { 460 Debug.log("Generated KEK : " + StringUtil.toHexString(kek) + " / " + kek.length, module); 461 } 462 463 return kek; 464 } 465 466 472 public PublicKey getValueLinkPublicKey() throws NoSuchAlgorithmException , InvalidKeySpecException { 473 String publicValue = (String ) props.get("payment.valuelink.publicValue"); 475 byte[] publicKeyBytes = StringUtil.fromHexString(publicValue); 476 477 DHParameterSpec dhParamSpec = this.getDHParameterSpec(); 479 480 KeyFactory keyFactory = KeyFactory.getInstance("DH"); 482 BigInteger publicKeyInt = new BigInteger (publicKeyBytes); 483 DHPublicKeySpec dhPublicSpec = new DHPublicKeySpec(publicKeyInt, dhParamSpec.getP(), dhParamSpec.getG()); 484 PublicKey vlPublic = keyFactory.generatePublic(dhPublicSpec); 485 486 return vlPublic; 487 } 488 489 493 public PrivateKey getPrivateKey() throws InvalidKeySpecException , NoSuchAlgorithmException { 494 byte[] privateKeyBytes = this.getPrivateKeyBytes(); 495 496 DHParameterSpec dhParamSpec = this.getDHParameterSpec(); 498 499 KeyFactory keyFactory = KeyFactory.getInstance("DH"); 501 BigInteger privateKeyInt = new BigInteger (privateKeyBytes); 502 DHPrivateKeySpec dhPrivateSpec = new DHPrivateKeySpec(privateKeyInt, dhParamSpec.getP(), dhParamSpec.getG()); 503 PrivateKey privateKey = keyFactory.generatePrivate(dhPrivateSpec); 504 505 return privateKey; 506 } 507 508 512 public byte[] generateMwk() { 513 KeyGenerator keyGen = null; 514 try { 515 keyGen = KeyGenerator.getInstance("DES"); 516 } catch (NoSuchAlgorithmException e) { 517 Debug.logError(e, module); 518 } 519 520 SecretKey des1 = keyGen.generateKey(); 522 SecretKey des2 = keyGen.generateKey(); 523 524 if (des1 != null && des2 != null) { 525 byte[] desByte1 = des1.getEncoded(); 526 byte[] desByte2 = des2.getEncoded(); 527 byte[] desByte3 = des1.getEncoded(); 528 529 try { 531 if (DESKeySpec.isWeak(des1.getEncoded(), 0) || DESKeySpec.isWeak(des2.getEncoded(), 0)) { 532 return generateMwk(); 533 } 534 } catch (Exception e) { 535 Debug.logError(e, module); 536 } 537 538 byte[] des3 = copyBytes(desByte1, copyBytes(desByte2, desByte3, 0), 0); 539 return generateMwk(des3); 540 } else { 541 Debug.log("Null DES keys returned", module); 542 } 543 544 return null; 545 } 546 547 552 public byte[] generateMwk(byte[] desBytes) { 553 if (debug) { 554 Debug.log("DES Key : " + StringUtil.toHexString(desBytes) + " / " + desBytes.length, module); 555 } 556 SecretKeyFactory skf1 = null; 557 SecretKey mwk = null; 558 try { 559 skf1 = SecretKeyFactory.getInstance("DESede"); 560 } catch (NoSuchAlgorithmException e) { 561 Debug.logError(e, module); 562 } 563 DESedeKeySpec desedeSpec2 = null; 564 try { 565 desedeSpec2 = new DESedeKeySpec(desBytes); 566 } catch (InvalidKeyException e) { 567 Debug.logError(e, module); 568 } 569 if (skf1 != null && desedeSpec2 != null) { 570 try { 571 mwk = skf1.generateSecret(desedeSpec2); 572 } catch (InvalidKeySpecException e) { 573 Debug.logError(e, module); 574 } 575 } 576 if (mwk != null) { 577 return generateMwk(mwk); 578 } else { 579 return null; 580 } 581 } 582 583 588 public byte[] generateMwk(SecretKey mwkdes3) { 589 byte[] zeros = { 0, 0, 0, 0, 0, 0, 0, 0 }; 591 592 byte[] random = new byte[8]; 594 Random ran = new Random (); 595 ran.nextBytes(random); 596 597 598 Cipher cipher = this.getCipher(mwkdes3, Cipher.ENCRYPT_MODE); 600 601 byte[] encryptedZeros = new byte[0]; 603 try { 604 encryptedZeros = cipher.doFinal(zeros); 605 } catch (IllegalStateException e) { 606 Debug.logError(e, module); 607 } catch (IllegalBlockSizeException e) { 608 Debug.logError(e, module); 609 } catch (BadPaddingException e) { 610 Debug.logError(e, module); 611 } 612 613 byte[] newMwk = copyBytes(mwkdes3.getEncoded(), encryptedZeros, 0); 615 newMwk = copyBytes(random, newMwk, 0); 616 617 if (debug) { 618 Debug.log("Random 8 byte : " + StringUtil.toHexString(random), module); 619 Debug.log("Encrypted 0's : " + StringUtil.toHexString(encryptedZeros), module); 620 Debug.log("Decrypted MWK : " + StringUtil.toHexString(mwkdes3.getEncoded()) + " / " + mwkdes3.getEncoded().length, module); 621 Debug.log("Encrypted MWK : " + StringUtil.toHexString(newMwk) + " / " + newMwk.length, module); 622 } 623 624 return newMwk; 625 } 626 627 632 public byte[] encryptViaKek(byte[] content) { 633 return cryptoViaKek(content, Cipher.ENCRYPT_MODE); 634 } 635 636 641 public byte[] decryptViaKek(byte[] content) { 642 return cryptoViaKek(content, Cipher.DECRYPT_MODE); 643 } 644 645 649 public String getDateString() { 650 String format = (String ) props.get("payment.valuelink.timestamp"); 651 SimpleDateFormat sdf = new SimpleDateFormat (format); 652 return sdf.format(new Date ()); 653 } 654 655 659 public Long getWorkingKeyIndex() { 660 if (this.mwkIndex == null) { 661 synchronized(this) { 662 if (this.mwkIndex == null) { 663 this.mwkIndex = this.getGenericValue().getLong("workingKeyIndex"); 664 } 665 } 666 } 667 668 if (debug) { 669 Debug.log("Current Working Key Index : " + this.mwkIndex, module); 670 } 671 672 return this.mwkIndex; 673 } 674 675 680 public String getAmount(Double amount) { 681 if (amount == null) { 682 return "0.00"; 683 } 684 String currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00"); 685 DecimalFormat formatter = new DecimalFormat (currencyFormat); 686 String amountString = formatter.format(amount.doubleValue()); 687 Double newAmount = null; 688 try { 689 newAmount = new Double (formatter.parse(amountString).doubleValue()); 690 } catch (ParseException e) { 691 Debug.logError(e, "Unable to parse amount Double"); 692 } 693 694 String formattedString = null; 695 if (newAmount != null) { 696 double amountDouble = newAmount.doubleValue() * 100; 697 formattedString = new String (new Integer (new Double (amountDouble).intValue()).toString()); 698 } 699 return formattedString; 700 } 701 702 707 public Double getAmount(String amount) { 708 if (amount == null) { 709 return new Double (0.00); 710 } 711 Double doubleAmount = new Double (amount); 712 return new Double (doubleAmount.doubleValue() / 100); 713 } 714 715 public String getCurrency(String currency) { 716 return "840"; } 718 719 724 public Map getInitialRequestMap(Map context) { 725 Map request = new HashMap (); 726 727 request.put("MerchID", merchantId + terminalId); 729 request.put("AltMerchNo", props.get("payment.valuelink.altMerchantId")); 730 731 String modes = (String ) props.get("payment.valuelink.modes"); 733 if (modes != null && modes.length() > 0) { 734 request.put("Modes", modes); 735 } 736 737 String merchTime = (String ) context.get("MerchTime"); 739 if (merchTime == null) { 740 merchTime = this.getDateString(); 741 } 742 request.put("MerchTime", merchTime); 743 744 String termTxNo = (String ) context.get("TermTxnNo"); 746 if (termTxNo == null) { 747 termTxNo = delegator.getNextSeqId("ValueLinkKey").toString(); 748 } 749 request.put("TermTxnNo", termTxNo); 750 751 request.put("EncryptID", this.getWorkingKeyIndex()); 753 754 if (debug) { 755 Debug.log("Created Initial Request Map : " + request, module); 756 } 757 758 return request; 759 } 760 761 765 public GenericValue getGenericValue() { 766 GenericValue value = null; 767 try { 768 value = delegator.findByPrimaryKeyCache("ValueLinkKey", UtilMisc.toMap("merchantId", merchantId)); 769 } catch (GenericEntityException e) { 770 Debug.logError(e, module); 771 } 772 if (value == null) { 773 throw new RuntimeException ("No ValueLinkKey record found for Merchant ID : " + merchantId); 774 } 775 return value; 776 } 777 778 781 public void reload() { 782 this.kek = null; 783 this.mwk = null; 784 this.mwkIndex = null; 785 } 786 787 protected DHParameterSpec getDHParameterSpec() { 789 String primeHex = (String ) props.get("payment.valuelink.prime"); 790 String genString = (String ) props.get("payment.valuelink.generator"); 791 792 byte[] primeByte = StringUtil.fromHexString(primeHex); 794 BigInteger prime = new BigInteger (1, primeByte); BigInteger generator = new BigInteger (genString); 796 797 DHParameterSpec dhParamSpec = new DHParameterSpec(prime, generator, 1024); 799 800 return dhParamSpec; 801 } 802 803 protected byte[] cryptoViaKek(byte[] content, int mode) { 805 Cipher cipher = this.getCipher(this.getKekKey(), mode); 807 byte[] dec = new byte[0]; 808 try { 809 dec = cipher.doFinal(content); 810 } catch (IllegalStateException e) { 811 Debug.logError(e, module); 812 } catch (IllegalBlockSizeException e) { 813 Debug.logError(e, module); 814 } catch (BadPaddingException e) { 815 Debug.logError(e, module); 816 } 817 return dec; 818 } 819 820 protected Cipher getCipher(SecretKey key, int mode) { 822 byte[] zeros = { 0, 0, 0, 0, 0, 0, 0, 0 }; 823 IvParameterSpec iv = new IvParameterSpec(zeros); 824 825 Cipher mwkCipher = null; 827 try { 828 mwkCipher = Cipher.getInstance("DESede/CBC/NoPadding"); 829 } catch (NoSuchAlgorithmException e) { 830 Debug.logError(e, module); 831 return null; 832 } catch (NoSuchPaddingException e) { 833 Debug.logError(e, module); 834 } 835 try { 836 mwkCipher.init(mode, key, iv); 837 } catch (InvalidKeyException e) { 838 Debug.logError(e, "Invalid key", module); 839 } catch (InvalidAlgorithmParameterException e) { 840 Debug.logError(e, module); 841 } 842 return mwkCipher; 843 } 844 845 protected byte[] getPinCheckSum(byte[] pinBytes) { 846 byte[] checkSum = new byte[1]; 847 checkSum[0] = 0; 848 for (int i = 0; i < pinBytes.length; i++) { 849 checkSum[0] += pinBytes[i]; 850 } 851 return checkSum; 852 } 853 854 protected byte[] getRandomBytes(int length) { 855 Random rand = new Random (); 856 byte[] randomBytes = new byte[length]; 857 rand.nextBytes(randomBytes); 858 return randomBytes; 859 } 860 861 protected SecretKey getMwkKey() { 862 if (mwk == null) { 863 mwk = this.getDesEdeKey(getByteRange(getMwk(), 8, 24)); 864 } 865 866 if (debug) { 867 Debug.log("Raw MWK : " + StringUtil.toHexString(getMwk()), module); 868 Debug.log("MWK : " + StringUtil.toHexString(mwk.getEncoded()), module); 869 } 870 871 return mwk; 872 } 873 874 protected SecretKey getKekKey() { 875 if (kek == null) { 876 kek = this.getDesEdeKey(getKek()); 877 } 878 879 if (debug) { 880 Debug.log("Raw KEK : " + StringUtil.toHexString(getKek()), module); 881 Debug.log("KEK : " + StringUtil.toHexString(kek.getEncoded()), module); 882 } 883 884 return kek; 885 } 886 887 protected SecretKey getDesEdeKey(byte[] rawKey) { 888 SecretKeyFactory skf = null; 889 try { 890 skf = SecretKeyFactory.getInstance("DESede"); 891 } catch (NoSuchAlgorithmException e) { 892 Debug.logError(e, module); 894 return null; 895 } 896 897 if (rawKey.length > 0) { 899 DESedeKeySpec desedeSpec1 = null; 900 try { 901 desedeSpec1 = new DESedeKeySpec(rawKey); 902 } catch (InvalidKeyException e) { 903 Debug.logError(e, "Not a valid DESede key", module); 904 return null; 905 } 906 907 SecretKey key = null; 909 try { 910 key = skf.generateSecret(desedeSpec1); 911 } catch (InvalidKeySpecException e) { 912 Debug.logError(e, module); 913 } 914 return key; 915 } else { 916 throw new RuntimeException ("No valid DESede key available"); 917 } 918 } 919 920 protected byte[] getMwk() { 921 return StringUtil.fromHexString(this.getGenericValue().getString("workingKey")); 922 } 923 924 protected byte[] getKek() { 925 return StringUtil.fromHexString(this.getGenericValue().getString("exchangeKey")); 926 } 927 928 protected byte[] getPrivateKeyBytes() { 929 return StringUtil.fromHexString(this.getGenericValue().getString("privateKey")); 930 } 931 932 protected Map parseResponse(String response) { 933 if (debug) { 934 Debug.log("Raw Response : " + response, module); 935 } 936 937 String subResponse = response.toLowerCase(); 939 int firstIndex = subResponse.indexOf("<tr>"); 940 int lastIndex = subResponse.lastIndexOf("</tr>"); 941 subResponse = subResponse.substring(firstIndex, lastIndex); 942 943 String history = null; 945 List historyMapList = null; 946 if (subResponse.indexOf("<table") > -1) { 947 int startHistory = subResponse.indexOf("<table"); 948 int endHistory = subResponse.indexOf("</table>") + 8; 949 history = subResponse.substring(startHistory, endHistory); 950 951 subResponse = StringUtil.replaceString(subResponse, history, "[_HISTORY_]"); 953 954 historyMapList = this.parseHistoryResponse(history); 956 } 957 958 subResponse = StringUtil.replaceString(subResponse, "</tr>", "|"); 960 961 subResponse = StringUtil.replaceString(subResponse, "</td><td>", "="); 963 964 subResponse = StringUtil.replaceString(subResponse, "<tr>", ""); 966 subResponse = StringUtil.replaceString(subResponse, "<td>", ""); 967 subResponse = StringUtil.replaceString(subResponse, "</td>", ""); 968 969 Map responseMap = StringUtil.strToMap(subResponse, true); 971 972 responseMap.put("_rawHtmlResponse", response); 974 975 if (history != null) { 977 responseMap.put("_rawHistoryHtml", history); 978 responseMap.put("history", historyMapList); 979 } 980 981 if (debug) { 982 Debug.log("Response Map : " + responseMap, module); 983 } 984 985 return responseMap; 986 } 987 988 private List parseHistoryResponse(String response) { 989 if (debug) { 990 Debug.log("Raw History : " + response, module); 991 } 992 993 String subResponse = response.toLowerCase(); 995 int firstIndex = subResponse.indexOf("<tr>"); 996 int lastIndex = subResponse.lastIndexOf("</tr>"); 997 subResponse = subResponse.substring(firstIndex, lastIndex); 998 999 subResponse = StringUtil.replaceString(subResponse, "<td>", ""); 1001 subResponse = StringUtil.replaceString(subResponse, "</td>", "|"); 1002 1003 String testResponse = StringUtil.replaceString(subResponse, "<tr>", ""); 1005 testResponse = StringUtil.replaceString(testResponse, "</tr>", ""); 1006 testResponse = StringUtil.replaceString(testResponse, "|", ""); 1007 testResponse = testResponse.trim(); 1008 if (testResponse.length() == 0) { 1009 if (debug) { 1010 Debug.log("History did not contain any fields, returning null", module); 1011 } 1012 return null; 1013 } 1014 1015 int valueStart = subResponse.indexOf("</tr>"); 1017 String keys = subResponse.substring(4, valueStart - 1); 1018 String values = subResponse.substring(valueStart + 9, subResponse.length() - 6); 1019 1020 values = StringUtil.replaceString(values, "|</tr><tr>", "&"); 1022 List valueList = StringUtil.split(values, "&"); 1023 1024 List valueMap = new ArrayList (); 1026 for (int i = 0; i < valueList.size(); i++) { 1027 valueMap.add(StringUtil.createMap(StringUtil.split(keys, "|"), StringUtil.split((String ) valueList.get(i), "|"))); 1028 } 1029 1030 if (debug) { 1031 Debug.log("History Map : " + valueMap, module); 1032 } 1033 1034 return valueMap; 1035 } 1036 1037 1044 public static byte[] getByteRange(byte[] bytes, int offset, int length) { 1045 byte[] newBytes = new byte[length]; 1046 for (int i = 0; i < length; i++) { 1047 newBytes[i] = bytes[offset + i]; 1048 } 1049 return newBytes; 1050 } 1051 1052 1059 public static byte[] copyBytes(byte[] source, byte[] target, int position) { 1060 byte[] newBytes = new byte[target.length + source.length]; 1061 for (int i = 0, n = 0, x = 0; i < newBytes.length; i++) { 1062 if (i < position || i > (position + source.length - 2)) { 1063 newBytes[i] = target[n]; 1064 n++; 1065 } else { 1066 for (; x < source.length; x++) { 1067 newBytes[i] = source[x]; 1068 if (source.length - 1 > x) { 1069 i++; 1070 } 1071 } 1072 } 1073 } 1074 return newBytes; 1075 } 1076} 1077 | Popular Tags |