ホームページ  >  記事  >  Java  >  Java 機密情報暗号化処理のサンプルコード共有

Java 機密情報暗号化処理のサンプルコード共有

黄舟
黄舟オリジナル
2017-03-18 10:22:493090ブラウズ

この記事では主に、Java での機密情報の暗号化処理に関する関連知識を紹介します: 1) 機密情報の暗号化処理のために実装したいこと、2) 機密情報の暗号化処理のために行ったこと、3) 機密情報の暗号化を実装する方法。非常に優れた参考値です。以下のエディターで見てみましょう

1. 機密情報を暗号化するときに何を達成したいですか? システムは多くの場合、ユーザーの機密情報を暗号化する必要があり、機密情報が異なれば暗号化要件も異なります。

たとえば、パスワードを暗号化する場合、多くの場合、元に戻せる必要はありません。ユーザーがパスワードを入力すると、システムの暗号化ルールが使用され、暗号化されて保存されたパスワードがエンコード後に直接比較され、その比較結果を取得することで、

ユーザー ログイン

情報の正当性を証明できます。

その後、データベースから削除されることによるデータ漏洩を防ぐために、一部の機密情報 (ID 番号、携帯電話番号など) を暗号化する必要がある場合があります。このようなデータは暗号化する必要があるだけでなく、表示やその他のビジネス シナリオでは完全に表示またはマスクする必要があるため、暗号化されたコンテンツを復号化する必要があります。

2. 機密情報を暗号化するために私が行ったこと

最近、プロジェクトでこの要件を達成するために、いくつかの簡単な設計が行われました:

注: 運用データを維持する際のクエリの利便性を考慮して、aes が使用されます。ここでの暗号化方法、暗号化方法は

mysql

の aes 暗号化結果と同じであるため、SQL で hex 関数と aes_encrypt 関数を直接使用してクエリを実行できます。暗号化ソルトは設定ファイルに保存できます。

1. カスタム アノテーションを使用します。PO の各クラスで暗号化および復号化する必要があるフィールドは、このアノテーションを使用して追加できます。メソッドの実装は Java を使用します。リフレクションとカスタム アノテーション

3. 暗号化および復号化する必要があるすべてのエンティティ オブジェクトは、Base クラスから継承する必要があります

4. エンティティ クラスが暗号化されるときに encrypt メソッドが呼び出され、復号化されるときに decrypt メソッドが呼び出されます。このようにして、オブジェクト内の機密データの暗号化と復号化を実現できます

3. 機密情報の暗号化の実装

まず効果を見てみましょう

注意非常に明確です。最初にオブジェクトの ID 番号を設定し、次に自己暗号化メソッドを実行して独自の参照を返し、オブジェクトの暗号化された JSON 文字列 文字列を出力します。自己復号化メソッドを実行して独自の参照を返し、出力します。オブジェクトの復号化された JSON 文字列を出力します。

2. 実装構造を設計する

crypt
   |
   |--annotation
   |    |--DecryptFiled
   |    |--EncryptFiled
   |--crypt
   |    |--EncryptDecryptInterface
   |--domain
   |    |--BaseInfo
   |    |--SimpleDomain
   |--utils
   |    |--MySqlUtils

2.1 アノテーションの実装を見てみましょう

/**
 * Created by bright on 2017/2/22.
 *
 * @author :
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptFiled {
  String value() default "";
}

自定义注解

2 つのアノテーションの実装は一貫しており、アノテーション名が異なるだけです。他のアノテーションのコードは投稿されません。 2.2 自己暗号化および自己復号化インターフェイスを定義します

Baseクラスは、このインターフェイスに自己暗号化および自己復号化メソッドを実装します

/**
 * Created by bright on 2017/2/22.
 *
 * @author :
 */
public interface EncryptDecryptInterface {
  public <T> T encryptSelf();
  public <T> T decryptSelf();
}

自定义接口

2.3 MysqlUtilsの実装

/**
 * Created by bright on 2017/2/22.
 *
 * @author :
 */
@Component
public class MySqlUtils {
  private static final String ENCRYPTTYPE= "AES";//加密方式
  private static final String ENCODING = "UTF-8";//加密时编码

  private static String MYSQLUTILSKEY = "aaa";//加密密盐
  private static MySqlUtils mysqlUtils;//单例
  private static Cipher encryptCipher ;//加密cipher
  private static Cipher decryptChipher;//解密chipher
  /**
   * 该方法可用在spring项目中使用配置文件设置密盐,默认值为123
   * @param key
   */
  @Value("${mysql.column.crypt.key:123}")
  public void setMysqlutilskey(String key){
    MySqlUtils.MYSQLUTILSKEY = key;
  }
  /**
   * encryptCipher、decryptChipher初始化
   */
  public static void init(){
    try {
      encryptCipher = Cipher.getInstance(ENCRYPTTYPE);
      decryptChipher = Cipher.getInstance(ENCRYPTTYPE);
      encryptCipher.init(Cipher.ENCRYPT_MODE, generateMySQLAESKey(MYSQLUTILSKEY, ENCODING));
      decryptChipher.init(Cipher.DECRYPT_MODE, generateMySQLAESKey(MYSQLUTILSKEY, ENCODING));
    } catch (InvalidKeyException e) {
      throw new RuntimeException(e);
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    } catch (NoSuchPaddingException e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * 单例获取方法实现
   * @return
   */
  public synchronized static MySqlUtils getInstance(){
    if(mysqlUtils == null){
      mysqlUtils = new MySqlUtils();
      init();
    }
    return mysqlUtils;
  }
  /**
   * 加密算法
   * @param encryptString
   * @return
   */
  public String mysqlAESEncrypt(String encryptString) {
    try{
      return new String(Hex.encodeHex(encryptCipher.doFinal(encryptString.getBytes(ENCODING)))).toUpperCase();
    } catch (BadPaddingException e) {
      throw new RuntimeException(e);
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    } catch (IllegalBlockSizeException e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * 解密算法
   * @param decryptString
   * @return
   */
  public String mysqlAESDecrypt(String decryptString){
    try {
      return new String(decryptChipher.doFinal(Hex.decodeHex(decryptString.toCharArray())));
    } catch (DecoderException nspe) {
      throw new RuntimeException(nspe);
    } catch (BadPaddingException nsae) {
      throw new RuntimeException(nsae);
    } catch (IllegalBlockSizeException ike) {
      throw new RuntimeException(ike);
    }
  }
  /**
   * 产生mysql-aes_encrypt
   * @param key 加密的密盐
   * @param encoding 编码
   * @return
   */
  public static SecretKeySpec generateMySQLAESKey(final String key, final String encoding) {
    try {
      final byte[] finalKey = new byte[16];
      int i = 0;
      for(byte b : key.getBytes(encoding))
        finalKey[i++%16] ^= b;
      return new SecretKeySpec(finalKey, "AES");
    } catch(UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }
}

MysqlUtils
2.4BaseInfoクラスの実装

/**
 * Created by bright on 2017/2/22.
 *
 * @author :
 */
public class BaseInfo implements Cloneable, EncryptDecryptInterface {
  /**
   * 拷贝一个对象,并对新对象进行加密
   * 该方法主要用在日志打印上,可防止原对象被加密而影响程序执行
   * @param <T>
   * @return
   */
  public <T extends BaseInfo> T cloneAndEncrypt() {
    T cloneT = null;
    try {
      cloneT = (T) this.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      return null;
    }
    if(cloneT !=null)
      return cloneT.encryptSelf();
    throw new RuntimeException("拷贝对象异常");
  }
  /**
   * 重写clone方法
   * @return
   * @throws CloneNotSupportedException
   */
  @Override
  protected Object clone() throws CloneNotSupportedException {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
      return null;
    }
  }
  /**
   * 实现自加密
   *
   * @param <T>
   * @return
   */
  public <T> T encryptSelf() {
    Field[] declaredFields = this.getClass().getDeclaredFields();
    try {
      if (declaredFields != null && declaredFields.length > 0) {
        for (Field field : declaredFields) {
          if (field.isAnnotationPresent(EncryptFiled.class) && field.getType().toString().endsWith("String")) {
            field.setAccessible(true);
            String fieldValue = (String) field.get(this);
            if (StringUtils.isNotEmpty(fieldValue)) {
              field.set(this, MySqlUtils.getInstance().mysqlAESEncrypt(fieldValue));
            }
            field.setAccessible(false);
          }
        }
      }
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
    return (T) this;
  }
  /**
   * 实现自解密
   *
   * @param <T>
   * @return
   */
  public <T> T decryptSelf() {
    Field[] declaredFields = this.getClass().getDeclaredFields();
    try {
      if (declaredFields != null && declaredFields.length > 0) {
        for (Field field : declaredFields) {
          if (field.isAnnotationPresent(DecryptFiled.class) && field.getType().toString().endsWith("String")) {
            field.setAccessible(true);
            String fieldValue = (String)field.get(this);
            if(StringUtils.isNotEmpty(fieldValue)) {
              field.set(this, MySqlUtils.getInstance().mysqlAESDecrypt(fieldValue));
            }
          }
        }
      }
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
    return (T) this;
  }
}

BaseInfo

2.5 単純なオブジェクト

/**
 * Created by bright on 2017/2/22.
 *
 * @author :
 */
public class SimpleDomain extends BaseInfo{
  @EncryptFiled
  @DecryptFiled
  private String id;
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
}

SimpleDomain

2.6

public class Client {
  @Test
  public void test(){
    SimpleDomain sd = new SimpleDomain();//要进行加密解密的实体类
    sd.setId("6029131988005021537");//注入身份证号
    System.out.println(JSON.toJSONString(sd.encryptSelf()));//执行自加密后输出
    System.out.println(JSON.toJSONString(sd.decryptSelf()));//执行自解密后输出
  }
}

Client
を呼び出してみましょう

以上がJava 機密情報暗号化処理のサンプルコード共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。