【问题标题】:How can I decrypt text from one application in another application with asymmetric encryption?如何使用非对称加密在另一个应用程序中解密来自一个应用程序的文本?
【发布时间】:2019-11-09 21:34:39
【问题描述】:

我试图了解如何在一个应用程序中解密我在单独的应用程序中加密的字符串。我可以在执行单个应用程序时执行此操作,并且我使用生成 PublicKey 的同一 KeyPair 中的 PrivateKey。但是,我想加密一个应用程序中的值,并解密另一个应用程序中的值。基本上,我有一个 Web 服务发送值,我不想被篡改到应用程序中,并且我计划使用非对称加密来处理它。如果我打算以错误的方式解决这个问题,请随时告诉我。

我尝试过各种加密技术,从对称开始。我遇到的问题是该值每次都被加密为相同的文本 - 如果我的目标是防止某人篡改一个值,这不是很有用 - 一旦他们知道某些文本的加密版本,他们将能够在任何请求中使用它。我一直在努力遵循这里的标准 - https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography 我可以让我的所有示例在单个事务中进行加密/解密 - 只是当我尝试在一个请求中加密并在第二个请求中解密时失败。

这是我当前的工作示例:

package com.ni.apps.cartencryptutil;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * Security class for encrypting and decrypting Strings (that also works in WC ver 7 and above)
 *
 * @author 
 *
 */
public class SecurityTools {
  private static final Logger logger = Logger.getLogger(SecurityTools.class);

  private Cipher cipher;
  private IvParameterSpec initVector;
  private SecretKey secretKey;
  PrivateKey privateKeyParam;
  PublicKey publicKeyParam;
  private static SecureRandom secureRandom = new SecureRandom();

  private static final String TRANSFORMATION = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
  private static final String ALGORITHM_SHORT = "RSA";
  private static final String RNG_ALGORITHM = "SHA1PRNG";
  private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
  private static final String UTF8 = "UTF-8";

  // exceptions
  private static final String _ERR_ILLEGAL_BLOCK_SIZE = "illegal block size exception.";
  private static final String _ERR_BAD_PADDING = "bad padding exception.";
  private static final String _ERR_INVALIDKEY = "invalidkey exception.";
  private static final String _ERR_PADDING = "padding exception.";
  private static final String _ERR_NO_SUCH_ALGORITHM = "no such algorithm exception.";
  private static final String _ERR_PASSPHRASE_IS_NULL = "passphrase is null.";
  private static final String _ERR_INVALID_ALGORITHM = "invalid algorithm exception.";
  private static final String _ERR_UNSUPPORTED_ENCODING = "encoding not supported.";
  private static final String _ERR_INVALID_KEY_SPEC = "invalid key spec exception.";

  /**
   * Constructor
   *
   * @throws EncryptionException
   */
  public SecurityTools() throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering Constructor");
    }
    try {
      cipher = Cipher.getInstance(ALGORITHM_SHORT);
      generateIV();
      generateKeys();
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } catch (NoSuchPaddingException nspe) {
      logger.error(_ERR_PADDING, nspe);
      throw new EncryptionException(_ERR_PADDING, nspe);
    }
    if (logger.isDebugEnabled()) {
      logger.debug("exiting Constructor");
    }
  }

  /**
   * Encrypts a given plain text String, and returns the encrypted String
   *
   * @param plainText
   * @return
   * @throws EncryptionException
   */
  public String encrypt(String plainText, PublicKey publicKey) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering encrypt");
    }

    String encryptedKey = null;
    try {
      byte[] byteToEncrypt = plainText.getBytes(UTF8);
      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
      byte[] encryptedBytes = cipher.doFinal(byteToEncrypt);
      encryptedKey = DatatypeConverter.printBase64Binary(encryptedBytes);
    } catch (IllegalArgumentException iae) {
      logger.error(_ERR_PASSPHRASE_IS_NULL, iae);
      throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL, iae);
    } catch (InvalidKeyException ike) {
      logger.error(_ERR_INVALIDKEY, ike);
      throw new EncryptionException(_ERR_INVALIDKEY, ike);
    } catch (BadPaddingException bpe) {
      logger.error(_ERR_BAD_PADDING, bpe);
      throw new EncryptionException(_ERR_BAD_PADDING, bpe);
    } catch (IllegalBlockSizeException bpe) {
      logger.error(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
      throw new EncryptionException(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
    } catch (UnsupportedEncodingException uee) {
      logger.error(_ERR_UNSUPPORTED_ENCODING, uee);
      throw new EncryptionException(_ERR_UNSUPPORTED_ENCODING, uee);
    } /*-catch (InvalidAlgorithmParameterException iape) {
      logger.error(_ERR_INVALID_ALGORITHM, iape);
      throw new EncryptionException(_ERR_INVALID_ALGORITHM, iape);
      }*/

    if (logger.isDebugEnabled()) {
      logger.debug("exiting encrypt");
    }

    return encryptedKey;
  }

  /**
   * Decrypts a given encrypted String, and returns the plain text String
   *
   * @param cipherTextStr
   * @return
   * @throws EncryptionException
   */
  public String decrypt(String cipherTextStr, PrivateKey privateKey) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering decrypt");
    }

    String cleartext = null;
    try {
      cipher.init(Cipher.DECRYPT_MODE, privateKey);
      byte[] plainByte = cipher.doFinal(DatatypeConverter.parseBase64Binary(cipherTextStr));
      cleartext = new String(plainByte);
    } /*-catch (InvalidAlgorithmParameterException iape) {
      logger.error(_ERR_INVALID_ALGORITHM, iape);
      throw new EncryptionException(_ERR_INVALID_ALGORITHM, iape);
      } */catch (IllegalArgumentException iae) {
      logger.error(_ERR_PASSPHRASE_IS_NULL, iae);
      throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL, iae);
    } catch (InvalidKeyException ike) {
      logger.error(_ERR_INVALIDKEY, ike);
      throw new EncryptionException(_ERR_INVALIDKEY, ike);
    } catch (BadPaddingException bpe) {
      logger.error(_ERR_BAD_PADDING, bpe);
      throw new EncryptionException(_ERR_BAD_PADDING, bpe);
    } catch (IllegalBlockSizeException bpe) {
      logger.error(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
      throw new EncryptionException(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
    }

    if (logger.isDebugEnabled()) {
      logger.debug("exiting decrypt");
    }

    return cleartext;
  }

  /**
   * Creates the IV using Secure Random Number Generator and an empty 16byte array
   *
   * @return
   */
  private void generateIV() {
    if (logger.isDebugEnabled()) {
      logger.debug("entering generateIV");
    }

    byte[] newSeed = secureRandom.generateSeed(16);
    secureRandom.setSeed(newSeed);
    byte[] byteIV = new byte[16];
    secureRandom.nextBytes(byteIV);
    initVector = new IvParameterSpec(byteIV);

    if (logger.isDebugEnabled()) {
      logger.debug("exiting generateIV");
    }
  }

  /**
   * Generates the Key used for decryption and encryption
   *
   * @throws EncryptionException
   */
  private void generateKeys() throws EncryptionException {

    try {
      String saltStr = "salty";// rbConfig.getString("salt");
      String passPhraseStr = "passy";// rbConfig.getString("passphrase");
      if (StringUtils.isEmpty(saltStr) || StringUtils.isEmpty(passPhraseStr)) {
        throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL);
      }

      KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
      keyGen.initialize(512); // key size specified here.
      KeyPair pair = keyGen.generateKeyPair();
      privateKeyParam = pair.getPrivate();
      publicKeyParam = pair.getPublic();

      /*-byte[] salt = saltStr.getBytes();
      int iterations = 10000;
      int keyLength = 128;

      SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
      SecretKey tmp = factory.generateSecret(new PBEKeySpec(passPhraseStr.toCharArray(), salt, iterations, keyLength));
      secretKey = new SecretKeySpec(tmp.getEncoded(), ALGORITHM_SHORT);*/
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } /*-catch (InvalidKeySpecException e) {
      logger.error(_ERR_INVALID_KEY_SPEC, e);
      throw new EncryptionException(_ERR_INVALID_KEY_SPEC, e);
      }*/

  }

  /**
   * Test method
   *
   * @param args
   */
  public static void main(String[] args) {
    String[] message = { "mktest", "9248547896548752345", "okok234234234okok467467",
        "12" };
    String result = null;
    try {
      SecurityTools secTool = new SecurityTools();
      PrivateKey priv = secTool.getPrivateKeyParam();
      PublicKey publ = secTool.getPublicKeyParam();
      String temp = "N5B1zgbvts3Vwrt6qyL/TBzt62HTFz0ISySx5HFu02oVq1YEhFLbrgdCndROX4/5hMpxCHGM8UJBSyZUfjD/DA==";
      // System.out.println("ASYMMETRIC TEST" + secTool.decrypt(temp, priv));

      for (String mess : message) {
        result = secTool.encrypt(mess, publ);
        System.out.println(result);
        result = secTool.decrypt(result, priv);
        System.out.println(result);
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
      e.printStackTrace();

    }
  }

  /**
   * @return the privateKeyParam
   */
  public PrivateKey getPrivateKeyParam() {
    return privateKeyParam;
  }

  /**
   * @return the publicKeyParam
   */
  public PublicKey getPublicKeyParam() {
    return publicKeyParam;
  }

  class EncryptionException extends Exception {

    private static final long serialVersionUID = 1L;

    public EncryptionException() {}

    public EncryptionException(String message, Throwable cause) {
      super(message, cause);
    }

    public EncryptionException(String message) {
      super(message);
    }

    public EncryptionException(Throwable cause) {
      super(cause);
    }
  }
}

当我按原样运行它时,它可以工作,因为主要是一次性完成加密和解密。但是,当我从运行中获取输出并将其存储在 main() 中的临时字符串中,然后取消注释 System.out.println("ASYMMETRIC TEST" + is when it failed with

com.ni.apps.cartencryptutil.SecurityTools$EncryptionException: bad padding exception.
    at com.ni.apps.cartencryptutil.SecurityTools.decrypt(SecurityTools.java:154)
    at com.ni.apps.cartencryptutil.SecurityTools.main(SecurityTools.java:239)
Caused by: javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at com.ni.apps.cartencryptutil.SecurityTools.decrypt(SecurityTools.java:141)
    ... 1 more

我认为我的问题是我每次都重新生成一个新的密钥对,它只能作为一对工作一次。因此,一旦我尝试将来自一个 KeyPair 的 PrivateKey 与使用完全不同的 KeyPair 加密的文本匹配,它就会失败。但我还没有找到在这种情况下你应该如何实现这一目标。

【问题讨论】:

  • 这是我找到的最接近答案的答案 - stackoverflow.com/questions/23086424/… - 我真的必须找到某种方法将私钥存储在两个应用程序之间的共享空间中吗?那时,为什么我不完全放弃加密,让应用程序 1 将其未加密的值存储在数据库中,然后应用程序 2 检索以确保它没有被篡改?当然有更好、更正确的方法来做到这一点!
  • 为什么不直接使用 SSL/TLS?
  • @JamesKPolk 事实是我不知道这是一个选项。这就是为什么我发布这个,试图找到我可以尝试的。在我搜索加密的一整天中,这没有出现,所以谢谢。有趣的是,它与我开车回家时想出的选项有点相似。我会让客户端 A 调用客户端 B,它会生成一个 ID 和一个盐并存储它。客户端 A 将使用该盐来加密我提供给它的 ID,以及它需要加密的其他数据。然后将所有内容发送回客户端 B 以用于验证。创建初始合约听起来类似于 SSL/TLS 方法
  • 我也意识到我最初的方法无论如何都是有缺陷的。只要加密值可以随时在目标系统中解密,该加密值是否在每个会话中更改都没有关系。一旦黑客对我希望我的源系统解密的任何给定字符串有一个有效的加密值,他就可以发送他想要的任何数据,如果他在之前的会话中看到了所需的加密值。由于我在这些请求中发送价格,因此不难获得任何所需金额的先前有效表示并将其用于其他调用

标签: java encryption public-key-encryption encryption-asymmetric


【解决方案1】:
package com.ni.apps.cartencryptutil;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.ni.apps.cartencryptutil.exceptions.EncryptionException;

/**
 * Security class for encrypting and decrypting Strings (that also works in WC ver 7 and above).
 *
 * @author mkohanek
 *
 */
public class SecurityTools {
  private static final Logger logger = Logger.getLogger(SecurityTools.class);

  private Cipher cipher;
  private IvParameterSpec initVector;
  private SecretKey secretKey;
  private transient ResourceBundle rbConfig;

  private static SecureRandom secureRandom = new SecureRandom();
  private static final String AES_ALGORITHM = "AES/CBC/PKCS5Padding";
  private static final String ALGORITHM_SHORT = "AES";
  private static final String PBE_ALGORITHM = "PBEWithMD5AndDES";
  private static final String UTF8 = "UTF-8";
  private static final int ITERATIONS = 10000;
  private static final int KEY_LENGTH = 128;

  // exceptions
  private static final String _ERR_ILLEGAL_BLOCK_SIZE = "illegal block size exception.";
  private static final String _ERR_BAD_PADDING = "bad padding exception.";
  private static final String _ERR_INVALIDKEY = "invalidkey exception.";
  private static final String _ERR_PADDING = "padding exception.";
  private static final String _ERR_NO_SUCH_ALGORITHM = "no such algorithm exception.";
  private static final String _ERR_PASSPHRASE_IS_NULL = "passphrase is null.";
  private static final String _ERR_SALT_IS_NULL = "salt is null.";
  private static final String _ERR_INVALID_ALGORITHM = "invalid algorithm exception.";
  private static final String _ERR_UNSUPPORTED_ENCODING = "encoding not supported.";
  private static final String _ERR_INVALID_KEY_SPEC = "invalid key spec exception.";

  /**
   * Constructor
   *
   * @param salt
   *          - for encryption, obtain salt from generateSalt(). for decryption, you should use the same salt used during encryption
   * @throws EncryptionException
   */
  public SecurityTools(String salt) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering Constructor");
    }
    try {
      loadProperties();
      cipher = Cipher.getInstance(AES_ALGORITHM);
      generateIV(salt);
      generateKey(salt);
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } catch (NoSuchPaddingException nspe) {
      logger.error(_ERR_PADDING, nspe);
      throw new EncryptionException(_ERR_PADDING, nspe);
    }
    if (logger.isDebugEnabled()) {
      logger.debug("exiting Constructor");
    }
  }

  /**
   * Constructor
   *
   * @param salt
   *          - for encryption, obtain salt from generateSalt(). for decryption, you should use the same salt used during encryption
   * @param passPhrase
   *          - Allows client to pass in a passphrase it wants to use rather than use the one this library defines. This must also be used when decrypting. The length limit for this key is 16
   *          characters
   * @throws EncryptionException
   */
  public SecurityTools(String salt, String passPhrase) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering Constructor");
    }
    try {
      loadProperties();
      cipher = Cipher.getInstance(AES_ALGORITHM);
      generateIV(salt);
      generateKey(salt, passPhrase);
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } catch (NoSuchPaddingException nspe) {
      logger.error(_ERR_PADDING, nspe);
      throw new EncryptionException(_ERR_PADDING, nspe);
    }
    if (logger.isDebugEnabled()) {
      logger.debug("exiting Constructor");
    }
  }

  /**
   * Encrypts a given plain text String, and returns the encrypted String
   *
   * @param plainText
   * @return
   * @throws EncryptionException
   */
  public String encrypt(String plainText) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering encrypt");
    }

    String encryptedKey = null;
    try {
      byte[] byteToEncrypt = plainText.getBytes(UTF8);
      cipher.init(Cipher.ENCRYPT_MODE, secretKey, initVector, new SecureRandom());
      byte[] encryptedBytes = cipher.doFinal(byteToEncrypt);
      encryptedKey = DatatypeConverter.printBase64Binary(encryptedBytes);
    } catch (IllegalArgumentException iae) {
      logger.error(_ERR_PASSPHRASE_IS_NULL, iae);
      throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL, iae);
    } catch (InvalidKeyException ike) {
      logger.error(_ERR_INVALIDKEY, ike);
      throw new EncryptionException(_ERR_INVALIDKEY, ike);
    } catch (BadPaddingException bpe) {
      logger.error(_ERR_BAD_PADDING, bpe);
      throw new EncryptionException(_ERR_BAD_PADDING, bpe);
    } catch (IllegalBlockSizeException bpe) {
      logger.error(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
      throw new EncryptionException(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
    } catch (UnsupportedEncodingException uee) {
      logger.error(_ERR_UNSUPPORTED_ENCODING, uee);
      throw new EncryptionException(_ERR_UNSUPPORTED_ENCODING, uee);
    } catch (InvalidAlgorithmParameterException iape) {
      logger.error(_ERR_INVALID_ALGORITHM, iape);
      throw new EncryptionException(_ERR_INVALID_ALGORITHM, iape);
    }

    if (logger.isDebugEnabled()) {
      logger.debug("exiting encrypt");
    }

    return encryptedKey;
  }

  /**
   * Decrypts a given encrypted String, and returns the plain text String
   *
   * @param cipherTextStr
   * @return
   * @throws EncryptionException
   */
  public String decrypt(String cipherTextStr) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering decrypt");
    }

    String cleartext = null;
    try {
      cipher.init(Cipher.DECRYPT_MODE, secretKey, initVector);
      byte[] plainByte = cipher.doFinal(DatatypeConverter.parseBase64Binary(cipherTextStr));
      cleartext = new String(plainByte);
    } catch (InvalidAlgorithmParameterException iape) {
      logger.error(_ERR_INVALID_ALGORITHM, iape);
      throw new EncryptionException(_ERR_INVALID_ALGORITHM, iape);
    } catch (IllegalArgumentException iae) {
      logger.error(_ERR_PASSPHRASE_IS_NULL, iae);
      throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL, iae);
    } catch (InvalidKeyException ike) {
      logger.error(_ERR_INVALIDKEY, ike);
      throw new EncryptionException(_ERR_INVALIDKEY, ike);
    } catch (BadPaddingException bpe) {
      logger.error(_ERR_BAD_PADDING, bpe);
      throw new EncryptionException(_ERR_BAD_PADDING, bpe);
    } catch (IllegalBlockSizeException bpe) {
      logger.error(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
      throw new EncryptionException(_ERR_ILLEGAL_BLOCK_SIZE, bpe);
    }

    if (logger.isDebugEnabled()) {
      logger.debug("exiting decrypt");
    }

    return cleartext;
  }

  /**
   * Creates the IV using Secure Random Number Generator and an empty 16byte array
   *
   * @return
   */
  private void generateIV(String salt) {
    if (logger.isDebugEnabled()) {
      logger.debug("entering generateIV");
    }

    byte[] newSeed = DatatypeConverter.parseBase64Binary(salt);
    initVector = new IvParameterSpec(newSeed);

    if (logger.isDebugEnabled()) {
      logger.debug("exiting generateIV");
    }
  }

  /**
   * Generates the Key used for decryption and encryption using passphrase from properties file on library
   *
   ** @param saltStr
   * @return
   * @throws EncryptionException
   */
  private void generateKey(String saltStr) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering generateKey");
    }

    try {
      String passPhraseStr = rbConfig.getString("passphrase");
      if (StringUtils.isEmpty(passPhraseStr)) {
        throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL);
      }
      if (StringUtils.isEmpty(saltStr)) {
        throw new EncryptionException(_ERR_SALT_IS_NULL);
      }

      byte[] salt = DatatypeConverter.parseBase64Binary(saltStr);

      SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGORITHM);
      SecretKey tmp = factory.generateSecret(new PBEKeySpec(passPhraseStr.toCharArray(), salt, ITERATIONS, KEY_LENGTH));
      secretKey = new SecretKeySpec(tmp.getEncoded(), ALGORITHM_SHORT);
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } catch (InvalidKeySpecException e) {
      logger.error(_ERR_INVALID_KEY_SPEC, e);
      throw new EncryptionException(_ERR_INVALID_KEY_SPEC, e);
    }

    if (logger.isDebugEnabled()) {
      logger.debug("exiting generateKey");
    }
  }

  /**
   * Generates the Key used for decryption and encryption using passphrase passed in
   *
   * @param saltStr
   * @param passPhrase
   * @throws EncryptionException
   */
  private void generateKey(String saltStr, String passPhrase) throws EncryptionException {
    if (logger.isDebugEnabled()) {
      logger.debug("entering generateKey");
    }

    try {
      if (StringUtils.isEmpty(passPhrase)) {
        throw new EncryptionException(_ERR_PASSPHRASE_IS_NULL);
      }
      if (StringUtils.isEmpty(saltStr)) {
        throw new EncryptionException(_ERR_SALT_IS_NULL);
      }

      byte[] salt = DatatypeConverter.parseBase64Binary(saltStr);

      SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGORITHM);
      SecretKey tmp = factory.generateSecret(new PBEKeySpec(passPhrase.toCharArray(), salt, ITERATIONS, KEY_LENGTH));
      secretKey = new SecretKeySpec(tmp.getEncoded(), ALGORITHM_SHORT);
    } catch (NoSuchAlgorithmException iae) {
      logger.error(_ERR_NO_SUCH_ALGORITHM, iae);
      throw new EncryptionException(_ERR_NO_SUCH_ALGORITHM, iae);
    } catch (InvalidKeySpecException e) {
      logger.error(_ERR_INVALID_KEY_SPEC, e);
      throw new EncryptionException(_ERR_INVALID_KEY_SPEC, e);
    }

    if (logger.isDebugEnabled()) {
      logger.debug("exiting generateKey");
    }
  }

  /**
   * This generates a random value of user defined size that can be used to encrypt data. The decrypting client will then need to access this value to be able to decrypt
   *
   * @return
   */
  public static String generateSaltStr(int size) {
    String salt = null;
    byte[] newSeed = secureRandom.generateSeed(size);
    salt = DatatypeConverter.printBase64Binary(newSeed);

    return salt;
  }

  /**
   * This generates a random 16 bit value that can be used to encrypt data. The decrypting client will then need to access this value to be able to decrypt
   *
   * @return
   */
  public static String generateSaltStr() {
    String salt = null;
    byte[] newSeed = secureRandom.generateSeed(16);
    salt = DatatypeConverter.printBase64Binary(newSeed);

    return salt;
  }

  /**
   * Loads properties files (call before attempting to read any properties files)
   */
  private void loadProperties() {
    try {
      rbConfig = ResourceBundle.getBundle("application", Locale.US);
    } catch (MissingResourceException ie) {
      logger.fatal(
          "FATAL: SecurityTools.loadProperties Cannot read the properties file.  Please ensure the file is on the classpath.");
    } catch (Exception e) {
      logger.fatal(
          "FATAL: SecurityTools.loadProperties Cannot read the properties file.  Please ensure the file is on the classpath.");
    }
  }

  /**
   * Test method
   *
   * @param args
   */
  public static void main(String[] args) {
    String[] message = { "mkohanek", "9248547896548752345", "okok234234234okok467467",
        "12" };
    String result = null;
    try {
      // ASYMMETRIC TEST - use this block to test values are usable over separate sessions by taking output from loop below and using it here for subsequent calls
      // String previousSalt = "jriUh+01HlHw4g3mO9PLcw==";
      // SecurityTools asSecTool = new SecurityTools(previousSalt);
      // String previousEncryptedValue = "nFVxkzdx+psiUVkCW5NztQ==";
      // System.out.println("should decrypt to an expected value - " + asSecTool.decrypt(previousEncryptedValue));
      // END ASYMMETRIC TEST

      // SYMMETRIC TEST - tests that single requests will encrypt and decrypt successfully
      String salt = generateSaltStr(16);
      System.out.println("salt - " + salt);
      SecurityTools secTool = new SecurityTools(salt);
      for (String mess : message) {
        result = secTool.encrypt(mess);
        System.out.println(result);
        result = secTool.decrypt(result);
        System.out.println(result);
      }
      // END SYMMETRIC TEST
    } catch (Exception e) {
      System.out.println(e.getMessage());
      e.printStackTrace();

    }
  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-14
    • 2018-08-30
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    相关资源
    最近更新 更多