📄 valuelinkapi.java
字号:
try { kekTestC = cipher.doFinal(kekTestB); } catch (Exception e) { Debug.logError(e, module); } if (!kekOnly) { // public key (just Y) BigInteger y = publicKey.getY(); byte[] yBytes = y.toByteArray(); String yHex = StringUtil.toHexString(yBytes); buf.append("======== Begin Public Key (Y @ " + yBytes.length + " / " + yHex.length() + ") ========\n"); buf.append(yHex + "\n"); buf.append("======== End Public Key ========\n\n"); // private key (just X) BigInteger x = privateKey.getX(); byte[] xBytes = x.toByteArray(); String xHex = StringUtil.toHexString(xBytes); buf.append("======== Begin Private Key (X @ " + xBytes.length + " / " + xHex.length() + ") ========\n"); buf.append(xHex + "\n"); buf.append("======== End Private Key ========\n\n"); // private key (full) byte[] privateBytes = privateKey.getEncoded(); String privateHex = StringUtil.toHexString(privateBytes); buf.append("======== Begin Private Key (Full @ " + privateBytes.length + " / " + privateHex.length() + ") ========\n"); buf.append(privateHex + "\n"); buf.append("======== End Private Key ========\n\n"); } if (kekBytes != null) { buf.append("======== Begin KEK (" + kekBytes.length + ") ========\n"); buf.append(StringUtil.toHexString(kekBytes) + "\n"); buf.append("======== End KEK ========\n\n"); buf.append("======== Begin KEK (DES) (" + loadKekBytes.length + ") ========\n"); buf.append(StringUtil.toHexString(loadKekBytes) + "\n"); buf.append("======== End KEK (DES) ========\n\n"); buf.append("======== Begin KEK Test (" + kekTestC.length + ") ========\n"); buf.append(StringUtil.toHexString(kekTestC) + "\n"); buf.append("======== End KEK Test ========\n\n"); } else { Debug.logError("KEK came back empty", module); } return buf; } /** * Create a set of public/private keys using ValueLinks defined parameters * @return KeyPair object containing both public and private keys * @throws NoSuchAlgorithmException * @throws InvalidAlgorithmParameterException */ public KeyPair createKeys() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeySpecException { // initialize the parameter spec DHPublicKey publicKey = (DHPublicKey) this.getValueLinkPublicKey(); DHParameterSpec dhParamSpec = publicKey.getParams(); //Debug.log(dhParamSpec.getP().toString() + " / " + dhParamSpec.getG().toString(), module); // create the public/private key pair using parameters defined by valuelink KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); keyGen.initialize(dhParamSpec); KeyPair keyPair = keyGen.generateKeyPair(); return keyPair; } /** * Generate a key exchange key for use in encrypting the mwk * @param privateKey The private key for the merchant * @return byte array containing the kek * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException * @throws InvalidKeyException */ public byte[] generateKek(PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException { // get the ValueLink public key PublicKey vlPublic = this.getValueLinkPublicKey(); // generate shared secret key KeyAgreement ka = KeyAgreement.getInstance("DH"); ka.init(privateKey); ka.doPhase(vlPublic, true); byte[] secretKey = ka.generateSecret(); if (debug) { Debug.log("Secret Key : " + StringUtil.toHexString(secretKey) + " / " + secretKey.length, module); } // generate 3DES from secret key using VL algorithm (KEK) MessageDigest md = MessageDigest.getInstance("SHA1"); byte[] digest = md.digest(secretKey); byte[] des2 = getByteRange(digest, 0, 16); byte[] first8 = getByteRange(des2, 0, 8); byte[] kek = copyBytes(des2, first8, 0); if (debug) { Debug.log("Generated KEK : " + StringUtil.toHexString(kek) + " / " + kek.length, module); } return kek; } /** * Get a public key object for the ValueLink supplied public key * @return PublicKey object of ValueLinks's public key * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public PublicKey getValueLinkPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException { // read the valuelink public key String publicValue = (String) props.get("payment.valuelink.publicValue"); byte[] publicKeyBytes = StringUtil.fromHexString(publicValue); // initialize the parameter spec DHParameterSpec dhParamSpec = this.getDHParameterSpec(); // load the valuelink public key KeyFactory keyFactory = KeyFactory.getInstance("DH"); BigInteger publicKeyInt = new BigInteger(publicKeyBytes); DHPublicKeySpec dhPublicSpec = new DHPublicKeySpec(publicKeyInt, dhParamSpec.getP(), dhParamSpec.getG()); PublicKey vlPublic = keyFactory.generatePublic(dhPublicSpec); return vlPublic; } /** * Get merchant Private Key * @return PrivateKey object for the merchant */ public PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException { byte[] privateKeyBytes = this.getPrivateKeyBytes(); // initialize the parameter spec DHParameterSpec dhParamSpec = this.getDHParameterSpec(); // load the private key KeyFactory keyFactory = KeyFactory.getInstance("DH"); BigInteger privateKeyInt = new BigInteger(privateKeyBytes); DHPrivateKeySpec dhPrivateSpec = new DHPrivateKeySpec(privateKeyInt, dhParamSpec.getP(), dhParamSpec.getG()); PrivateKey privateKey = keyFactory.generatePrivate(dhPrivateSpec); return privateKey; } /** * Generate a new MWK * @return Hex String of the new encrypted MWK ready for transmission to ValueLink */ public byte[] generateMwk() { KeyGenerator keyGen = null; try { keyGen = KeyGenerator.getInstance("DES"); } catch (NoSuchAlgorithmException e) { Debug.logError(e, module); } // generate the DES key 1 SecretKey des1 = keyGen.generateKey(); SecretKey des2 = keyGen.generateKey(); if (des1 != null && des2 != null) { byte[] desByte1 = des1.getEncoded(); byte[] desByte2 = des2.getEncoded(); byte[] desByte3 = des1.getEncoded(); // check for weak keys try { if (DESKeySpec.isWeak(des1.getEncoded(), 0) || DESKeySpec.isWeak(des2.getEncoded(), 0)) { return generateMwk(); } } catch (Exception e) { Debug.logError(e, module); } byte[] des3 = copyBytes(desByte1, copyBytes(desByte2, desByte3, 0), 0); return generateMwk(des3); } else { Debug.log("Null DES keys returned", module); } return null; } /** * Generate a new MWK * @param desBytes byte array of the DES key (24 bytes) * @return Hex String of the new encrypted MWK ready for transmission to ValueLink */ public byte[] generateMwk(byte[] desBytes) { if (debug) { Debug.log("DES Key : " + StringUtil.toHexString(desBytes) + " / " + desBytes.length, module); } SecretKeyFactory skf1 = null; SecretKey mwk = null; try { skf1 = SecretKeyFactory.getInstance("DESede"); } catch (NoSuchAlgorithmException e) { Debug.logError(e, module); } DESedeKeySpec desedeSpec2 = null; try { desedeSpec2 = new DESedeKeySpec(desBytes); } catch (InvalidKeyException e) { Debug.logError(e, module); } if (skf1 != null && desedeSpec2 != null) { try { mwk = skf1.generateSecret(desedeSpec2); } catch (InvalidKeySpecException e) { Debug.logError(e, module); } } if (mwk != null) { return generateMwk(mwk); } else { return null; } } /** * Generate a new MWK * @param mwkdes3 pre-generated DES3 SecretKey * @return Hex String of the new encrypted MWK ready for transmission to ValueLink */ public byte[] generateMwk(SecretKey mwkdes3) { // zeros for checksum byte[] zeros = { 0, 0, 0, 0, 0, 0, 0, 0 }; // 8 bytes random data byte[] random = new byte[8]; Random ran = new Random(); ran.nextBytes(random); // open a cipher using the new mwk Cipher cipher = this.getCipher(mwkdes3, Cipher.ENCRYPT_MODE); // make the checksum - encrypted 8 bytes of 0's byte[] encryptedZeros = new byte[0]; try { encryptedZeros = cipher.doFinal(zeros); } catch (IllegalStateException e) { Debug.logError(e, module); } catch (IllegalBlockSizeException e) { Debug.logError(e, module); } catch (BadPaddingException e) { Debug.logError(e, module); } // make the 40 byte MWK - random 8 bytes + key + checksum byte[] newMwk = copyBytes(mwkdes3.getEncoded(), encryptedZeros, 0); newMwk = copyBytes(random, newMwk, 0); if (debug) { Debug.log("Random 8 byte : " + StringUtil.toHexString(random), module); Debug.log("Encrypted 0's : " + StringUtil.toHexString(encryptedZeros), module); Debug.log("Decrypted MWK : " + StringUtil.toHexString(mwkdes3.getEncoded()) + " / " + mwkdes3.getEncoded().length, module); Debug.log("Encrypted MWK : " + StringUtil.toHexString(newMwk) + " / " + newMwk.length, module); } return newMwk; } /** * Use the KEK to encrypt a value usually the MWK * @param content byte array to encrypt * @return encrypted byte array */ public byte[] encryptViaKek(byte[] content) { return cryptoViaKek(content, Cipher.ENCRYPT_MODE); } /** * Ue the KEK to decrypt a value * @param content byte array to decrypt * @return decrypted byte array */ public byte[] decryptViaKek(byte[] content) { return cryptoViaKek(content, Cipher.DECRYPT_MODE); } /** * Returns a date string formatted as directed by ValueLink * @return ValueLink formatted date String */ public String getDateString() { String format = (String) props.get("payment.valuelink.timestamp"); SimpleDateFormat sdf = new SimpleDateFormat(format); return sdf.format(new Date()); } /** * Returns the current working key index * @return Long number of the current working key index */ public Long getWorkingKeyIndex() { if (this.mwkIndex == null) { synchronized(this) { if (this.mwkIndex == null) { this.mwkIndex = this.getGenericValue().getLong("workingKeyIndex"); } } } if (debug) { Debug.log("Current Working Key Index : " + this.mwkIndex, module); } return this.mwkIndex; } /** * Returns a ValueLink formatted amount String * @param amount Double value to format * @return Formatted String */ public String getAmount(Double amount) { if (amount == null) { return "0.00"; } String currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00"); DecimalFormat formatter = new DecimalFormat(currencyFormat); String amountString = formatter.format(amount.doubleValue()); Double newAmount = null; try { newAmount = new Double(formatter.parse(amountString).doubleValue()); } catch (ParseException e) { Debug.logError(e, "Unable to parse amount Double"); } String formattedString = null; if (newAmount != null) { double amountDouble = newAmount.doubleValue() * 100; formattedString = new String(new Integer(new Double(amountDouble).intValue()).toString()); } return formattedString; } /** * Returns a Double from a ValueLink formatted amount String * @param amount The ValueLink formatted amount String * @return Double object */ public Double getAmount(String amount) { if (amount == null) { return new Double(0.00); } Double doubleAmount = new Double(amount); return new Double(doubleAmount.doubleValue() / 100); } public String getCurrency(String currency) { return "840"; // todo make this multi-currency }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -