AES 256 GCM Java实现

时间:2020-05-24 15:01:55

标签: java encryption aes cryptojs aes-gcm

我正在尝试将以下AES-256-GCM加密的实现从NodeJS重写为Java。

Packet description

我得到了不同的输出,特别是auth标记部分。从外观上看,Java库没有任何方法可以获取auth标记,而我尝试从输出中对它进行字符串化的尝试失败。另外,我实际上不确定用公钥进行的第一个AES加密(为GCM生成随机缓冲区)是否与NodeJS对应的相同。 谁能指出我正确的方向?

NodeJS:

public encryptPassword(password: string, encryptionKey: string, encryptionKeyId: string): { time: string, encrypted: string } {
    const randKey = crypto.randomBytes(32);
    const iv = crypto.randomBytes(12);
    const rsaEncrypted = crypto.publicEncrypt({
      key: Buffer.from(encryptionKey, 'base64').toString(),
      // @ts-ignore
      padding: crypto.constants.RSA_PKCS1_PADDING,
    }, randKey);
    const cipher = crypto.createCipheriv('aes-256-gcm', randKey, iv);
    const time = Math.floor(Date.now() / 1000).toString();
    cipher.setAAD(Buffer.from(time));
    const aesEncrypted = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]);
    const sizeBuffer = Buffer.alloc(2, 0);
    sizeBuffer.writeInt16LE(rsaEncrypted.byteLength, 0);
    const authTag = cipher.getAuthTag();
    return {
      time,
      encrypted: Buffer.concat([
        Buffer.from([1, encryptionKeyId]),
        iv,
        sizeBuffer,
        rsaEncrypted, authTag, aesEncrypted])
        .toString('base64'),
    };
  }

Java:

 private static Pair<Long, String> encryptPaswword(String password, String encryptionPubKey, String encryptionKeyId) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidCipherTextException, InvalidAlgorithmParameterException {
    byte[] passwordAsByte = password.getBytes();
    String decoededPubKey = new String(Base64.decode(encryptionPubKey, Base64.NO_WRAP), StandardCharsets.UTF_8);
    decoededPubKey = decoededPubKey.replace("-----BEGIN PUBLIC KEY-----", "");
    decoededPubKey = decoededPubKey.replace("-----END PUBLIC KEY-----", "");

    SecureRandom random = new SecureRandom();
    byte[] randKey = new byte[32];
    random.nextBytes(randKey);
    byte[] iv = new byte[12];
    random.nextBytes(iv);
    long date = new Date().getTime() / 1000;

    ByteBuffer header = ByteBuffer.allocate(2);
    header.put(Integer.valueOf(1).byteValue());
    header.put(Integer.valueOf(Integer.parseInt(encryptionKeyId)).byteValue());
    ByteBuffer timeAAD = ByteBuffer.allocate(10);
    timeAAD.put(String.valueOf(date).getBytes());

    X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(decoededPubKey, Base64.NO_WRAP));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(publicSpec);
    Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
    rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] rsaEncrypted = rsaCipher.doFinal(randKey);

    ByteBuffer sizeBuff = ByteBuffer.allocate(2);
    sizeBuff.put(Integer.valueOf(rsaEncrypted.length).byteValue());

    final Cipher gcmCipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCMParameterSpec parameterSpec = new GCMParameterSpec(16 * Byte.SIZE, iv);
    gcmCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(randKey, "AES"), parameterSpec);
    gcmCipher.updateAAD(timeAAD);
    byte[] gcmText= gcmCipher.doFinal(passwordAsByte);

    ByteBuffer result = ByteBuffer.allocate(2+12+2+256+gcmText.length);
    result.put(header);
    result.put(iv);
    result.put(sizeBuff);
    result.put(rsaEncrypted);
    result.put(Arrays.copyOfRange(gcmText, gcmText.length - (16 / Byte.SIZE), gcmText.length));
    result.put(Arrays.copyOfRange(gcmText, 0, gcmText.length - (16 / Byte.SIZE)));

    return new Pair(new Long(date), Base64.encodeToString(result.array(), Base64.NO_WRAP));

0 个答案:

没有答案
相关问题