예제 #1
0
  /**
   * 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.logInfo(
          "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.logInfo("Generated KEK : " + StringUtil.toHexString(kek) + " / " + kek.length, module);
    }

    return kek;
  }
예제 #2
0
  protected SecretKey getKekKey() {
    if (kek == null) {
      kek = this.getDesEdeKey(getKek());
    }

    if (debug) {
      Debug.logInfo("Raw KEK : " + StringUtil.toHexString(getKek()), module);
      Debug.logInfo("KEK : " + StringUtil.toHexString(kek.getEncoded()), module);
    }

    return kek;
  }
예제 #3
0
  protected SecretKey getMwkKey() {
    if (mwk == null) {
      mwk = this.getDesEdeKey(getByteRange(getMwk(), 8, 24));
    }

    if (debug) {
      Debug.logInfo("Raw MWK : " + StringUtil.toHexString(getMwk()), module);
      Debug.logInfo("MWK : " + StringUtil.toHexString(mwk.getEncoded()), module);
    }

    return mwk;
  }
예제 #4
0
 /**
  * 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.logInfo(
         "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;
   }
 }
예제 #5
0
  /**
   * 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.logInfo("Random 8 byte : " + StringUtil.toHexString(random), module);
      Debug.logInfo("Encrypted 0's : " + StringUtil.toHexString(encryptedZeros), module);
      Debug.logInfo(
          "Decrypted MWK : "
              + StringUtil.toHexString(mwkdes3.getEncoded())
              + " / "
              + mwkdes3.getEncoded().length,
          module);
      Debug.logInfo(
          "Encrypted MWK : " + StringUtil.toHexString(newMwk) + " / " + newMwk.length, module);
    }

    return newMwk;
  }
예제 #6
0
  /**
   * Encrypt the defined pin using the configured keys
   *
   * @param pin Plain text String of the pin
   * @return Hex String of the encrypted pin (EAN) for transmission to ValueLink
   */
  public String encryptPin(String pin) {
    // get the Cipher
    Cipher mwkCipher = this.getCipher(this.getMwkKey(), Cipher.ENCRYPT_MODE);

    // pin to bytes
    byte[] pinBytes = pin.getBytes();

    // 7 bytes of random data
    byte[] random = this.getRandomBytes(7);

    // pin checksum
    byte[] checkSum = this.getPinCheckSum(pinBytes);

    // put all together
    byte[] eanBlock = new byte[16];
    int i;
    for (i = 0; i < random.length; i++) {
      eanBlock[i] = random[i];
    }
    eanBlock[7] = checkSum[0];
    for (i = 0; i < pinBytes.length; i++) {
      eanBlock[i + 8] = pinBytes[i];
    }

    // encrypy the ean
    String encryptedEanHex = null;
    try {
      byte[] encryptedEan = mwkCipher.doFinal(eanBlock);
      encryptedEanHex = StringUtil.toHexString(encryptedEan);
    } catch (IllegalStateException e) {
      Debug.logError(e, module);
    } catch (IllegalBlockSizeException e) {
      Debug.logError(e, module);
    } catch (BadPaddingException e) {
      Debug.logError(e, module);
    }

    if (debug) {
      Debug.logInfo("encryptPin : " + pin + " / " + encryptedEanHex, module);
    }

    return encryptedEanHex;
  }
예제 #7
0
  private StringBuffer outputKeyCreation(int loop, boolean kekOnly, String kekTest) {
    StringBuffer buf = new StringBuffer();
    loop++;

    if (loop > 100) {
      // only loop 100 times; then throw an exception
      throw new IllegalStateException("Unable to create 128 byte keys in 100 tries");
    }

    // place holder for the keys
    DHPrivateKey privateKey = null;
    DHPublicKey publicKey = null;

    if (!kekOnly) {
      KeyPair keyPair = null;
      try {
        keyPair = this.createKeys();
      } catch (NoSuchAlgorithmException e) {
        Debug.logError(e, module);
      } catch (InvalidAlgorithmParameterException e) {
        Debug.logError(e, module);
      } catch (InvalidKeySpecException e) {
        Debug.logError(e, module);
      }

      if (keyPair != null) {
        publicKey = (DHPublicKey) keyPair.getPublic();
        privateKey = (DHPrivateKey) keyPair.getPrivate();

        if (publicKey == null || publicKey.getY().toByteArray().length != 128) {
          // run again until we get a 128 byte public key for VL
          return this.outputKeyCreation(loop, kekOnly, kekTest);
        }
      } else {
        Debug.logInfo("Returned a null KeyPair", module);
        return this.outputKeyCreation(loop, kekOnly, kekTest);
      }
    } else {
      // use our existing private key to generate a KEK
      try {
        privateKey = (DHPrivateKey) this.getPrivateKey();
      } catch (Exception e) {
        Debug.logError(e, module);
      }
    }

    // the KEK
    byte[] kekBytes = null;
    try {
      kekBytes = this.generateKek(privateKey);
    } catch (NoSuchAlgorithmException e) {
      Debug.logError(e, module);
    } catch (InvalidKeySpecException e) {
      Debug.logError(e, module);
    } catch (InvalidKeyException e) {
      Debug.logError(e, module);
    }

    // the 3DES KEK value
    SecretKey loadedKek = this.getDesEdeKey(kekBytes);
    byte[] loadKekBytes = loadedKek.getEncoded();

    // test the KEK
    Cipher cipher = this.getCipher(this.getKekKey(), Cipher.ENCRYPT_MODE);
    byte[] kekTestB = {0, 0, 0, 0, 0, 0, 0, 0};
    byte[] kekTestC = new byte[0];
    if (kekTest != null) {
      kekTestB = StringUtil.fromHexString(kekTest);
    }

    // encrypt the test bytes
    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 @ ")
          .append(yBytes.length)
          .append(" / ")
          .append(yHex.length())
          .append(") ========\n");
      buf.append(yHex).append("\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 @ ")
          .append(xBytes.length)
          .append(" / ")
          .append(xHex.length())
          .append(") ========\n");
      buf.append(xHex).append("\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 @ ")
          .append(privateBytes.length)
          .append(" / ")
          .append(privateHex.length())
          .append(") ========\n");
      buf.append(privateHex).append("\n");
      buf.append("======== End Private Key ========\n\n");
    }

    if (kekBytes != null) {
      buf.append("======== Begin KEK (").append(kekBytes.length).append(") ========\n");
      buf.append(StringUtil.toHexString(kekBytes)).append("\n");
      buf.append("======== End KEK ========\n\n");

      buf.append("======== Begin KEK (DES) (").append(loadKekBytes.length).append(") ========\n");
      buf.append(StringUtil.toHexString(loadKekBytes)).append("\n");
      buf.append("======== End KEK (DES) ========\n\n");

      buf.append("======== Begin KEK Test (").append(kekTestC.length).append(") ========\n");
      buf.append(StringUtil.toHexString(kekTestC)).append("\n");
      buf.append("======== End KEK Test ========\n\n");
    } else {
      Debug.logError("KEK came back empty", module);
    }

    return buf;
  }