java用AES-GEM-256进行加解密

public class AesGcm256Utils {
  
      private static final SecureRandom SECURE_RANDOM = new SecureRandom();
  
      // Pre-configured Encryption Parameters
      public static int NonceBitSize = 128;
      public static int MacBitSize = 128;
      public static int KeyBitSize = 256;
  
      private AesGcm256Utils() {
      }
  
      /**
       * 生成随机key
       * @return
       */
      public static byte[] newKey(int len) {
          byte[] key = new byte[len];
          SECURE_RANDOM.nextBytes(key);
          return key;
      }
  
      /**
       * 生成随机nonce
       * @return
       */
      public static byte[] newNonce(int len) {
          byte[] iv = new byte[len];
          SECURE_RANDOM.nextBytes(iv);
          return iv;
      }
  
      /**
       * 加密
       * @param PlainText
       * @param key
       * @param iv
       * @return
       */
      public static byte[] encrypt(String PlainText, byte[] key, byte[] iv) {
          try {
              byte[] plainBytes = PlainText.getBytes("UTF-8");
  
              GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
              AEADParameters parameters = new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
  
              cipher.init(true, parameters);
  
              byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
              int retLen = cipher.processBytes(plainBytes, 0, plainBytes.length, encryptedBytes, 0);
              cipher.doFinal(encryptedBytes, retLen);
              return encryptedBytes;
          } catch (Exception e) {
              System.out.println(e.getMessage());
          }
  
          return null;
      }
  
  
      /**
       * 解密
       * @param EncryptedText
       * @param key
       * @param iv
       * @return
       */
      public static byte[] decrypt(byte[] EncryptedText, byte[] key, byte[] iv) {
          try {
              GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
              AEADParameters parameters = new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
  
              cipher.init(false, parameters);
              byte[] plainBytes = new byte[cipher.getOutputSize(EncryptedText.length)];
              int retLen = cipher.processBytes(EncryptedText, 0, EncryptedText.length, plainBytes, 0);
              cipher.doFinal(plainBytes, retLen);
  
             return plainBytes;
          } catch (IllegalArgumentException | IllegalStateException | DataLengthException | InvalidCipherTextException ex) {
              System.out.println(ex.getMessage());
          }
  
          return null;
      }
  
  }

  @Slf4j
  public class AesGcm256Test {
  
      public static void main(String[] args) throws Exception {
          // 生成随机32位key和12位nonce
          byte[] key = AesGcm256Utils.newKey(32);
          byte[] nonce = AesGcm256Utils.newNonce(12);
          String text = "123456";
          // 用key和nonce对text进行加密
          byte[] encrypt = AesGcm256Utils.encrypt(text, key, nonce);
          // 转成hex
          log.info(Utils.bytesToHex(encrypt));
          // 用key和nonce对text进行解密
          byte[] res = AesGcm256Utils.decrypt(encrypt, key, nonce);
          log.info(new String(res));
  
      }
  }

用AES-GEM-256可以对接口的数据体进行加密,我在工作中跟同事对接的时候,他的消息结构如下:



    Req:
    {
        "data":"",         -- Hex: AES-256-GCM加密, 业务JSON数据
        "security":{   
            "key":"",      -- AES Key encrypto by codeplus
            "nonce":""     -- Random number encrypto by codeplus
        },
        "sign":""          -- Hex : sha256(scard + data + security(key + nonce)
                           -- Signature by User private key generate via user codeplus
    }
    
    Resp:
    {
        "data":"",
        "sign":""          -- Hex : by SCPGS private key
        "security":{
            "key":"",     
            "nonce":""
        }
    }

他是用椭圆曲线非对称的加密方式。服务器有一对通讯层的公私钥,公钥是公开提供给客户端,私钥则是服务器自己保存的。其中业务JSON数据data就是用AES-256-GCM进行加密的,key和nonce是hex字符串,用服务器提供的通讯公钥来进行加密的。

而客户端自己也有秘钥对,公钥是给服务器那边保存,私钥则是客户端保存。

总体的流程是:客户端请求时用通讯公钥对key和nonce加密,用私钥进行签名;验签则是用通讯公钥,然后用自己的私钥对key和nonce解密。

posted @ 2021-03-12 18:21  Conwie  阅读(887)  评论(0编辑  收藏  举报