void CPDF_SecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict,
                                    CPDF_Array* pIdArray,
                                    const uint8_t* user_pass,
                                    uint32_t user_size,
                                    const uint8_t* owner_pass,
                                    uint32_t owner_size,
                                    FX_BOOL bDefault,
                                    uint32_t type) {
  int cipher = 0, key_len = 0;
  if (!LoadDict(pEncryptDict, type, cipher, key_len)) {
    return;
  }
  if (bDefault && (!owner_pass || owner_size == 0)) {
    owner_pass = user_pass;
    owner_size = user_size;
  }
  if (m_Revision >= 5) {
    int t = (int)time(nullptr);
    uint8_t sha[128];
    CRYPT_SHA256Start(sha);
    CRYPT_SHA256Update(sha, (uint8_t*)&t, sizeof t);
    CRYPT_SHA256Update(sha, m_EncryptKey, 32);
    CRYPT_SHA256Update(sha, (uint8_t*)"there", 5);
    CRYPT_SHA256Finish(sha, m_EncryptKey);
    AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey);
    if (bDefault) {
      AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE,
                         m_EncryptKey);
      AES256_SetPerms(pEncryptDict, m_Permissions,
                      pEncryptDict->GetBooleanBy("EncryptMetadata", true),
                      m_EncryptKey);
    }
    return;
  }
  if (bDefault) {
    uint8_t passcode[32];
    for (uint32_t i = 0; i < 32; i++) {
      passcode[i] =
          i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];
    }
    uint8_t digest[16];
    CRYPT_MD5Generate(passcode, 32, digest);
    if (m_Revision >= 3) {
      for (uint32_t i = 0; i < 50; i++)
        CRYPT_MD5Generate(digest, 16, digest);
    }
    uint8_t enckey[32];
    FXSYS_memcpy(enckey, digest, key_len);
    for (uint32_t i = 0; i < 32; i++) {
      passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];
    }
    CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);
    uint8_t tempkey[32];
    if (m_Revision >= 3) {
      for (uint8_t i = 1; i <= 19; i++) {
        for (int j = 0; j < key_len; j++)
          tempkey[j] = enckey[j] ^ i;
        CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);
      }
    }
    pEncryptDict->SetAtString("O", CFX_ByteString(passcode, 32));
  }
  CalcEncryptKey(m_pEncryptDict, (uint8_t*)user_pass, user_size, m_EncryptKey,
                 key_len, FALSE, pIdArray);
  if (m_Revision < 3) {
    uint8_t tempbuf[32];
    FXSYS_memcpy(tempbuf, defpasscode, 32);
    CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);
    pEncryptDict->SetAtString("U", CFX_ByteString(tempbuf, 32));
  } else {
    uint8_t md5[100];
    CRYPT_MD5Start(md5);
    CRYPT_MD5Update(md5, defpasscode, 32);
    if (pIdArray) {
      CFX_ByteString id = pIdArray->GetStringAt(0);
      CRYPT_MD5Update(md5, (uint8_t*)id.c_str(), id.GetLength());
    }
    uint8_t digest[32];
    CRYPT_MD5Finish(md5, digest);
    CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);
    uint8_t tempkey[32];
    for (uint8_t i = 1; i <= 19; i++) {
      for (int j = 0; j < key_len; j++) {
        tempkey[j] = m_EncryptKey[j] ^ i;
      }
      CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);
    }
    CRYPT_MD5Generate(digest, 16, digest + 16);
    pEncryptDict->SetAtString("U", CFX_ByteString(digest, 32));
  }
}
void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray,
        FX_LPCBYTE user_pass, FX_DWORD user_size,
        FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type)
{
    int cipher = 0, key_len = 0;
    if (!LoadDict(pEncryptDict, type, cipher, key_len)) {
        return;
    }
    if (bDefault && (owner_pass == NULL || owner_size == 0)) {
        owner_pass = user_pass;
        owner_size = user_size;
    }
    if (m_Revision >= 5) {
        int t = (int)time(NULL);
        FX_BYTE sha[128];
        CRYPT_SHA256Start(sha);
        CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t);
        CRYPT_SHA256Update(sha, m_EncryptKey, 32);
        CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5);
        CRYPT_SHA256Finish(sha, m_EncryptKey);
        AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey);
        if (bDefault) {
            AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey);
            AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey);
        }
        return;
    }
    if (bDefault) {
        FX_BYTE passcode[32];
        FX_DWORD i;
        for (i = 0; i < 32; i ++) {
            passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size];
        }
        FX_BYTE digest[16];
        CRYPT_MD5Generate(passcode, 32, digest);
        if (m_Revision >= 3) {
            for (int i = 0; i < 50; i ++) {
                CRYPT_MD5Generate(digest, 16, digest);
            }
        }
        FX_BYTE enckey[32];
        FXSYS_memcpy32(enckey, digest, key_len);
        for (i = 0; i < 32; i ++) {
            passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size];
        }
        CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len);
        FX_BYTE tempkey[32];
        if (m_Revision >= 3) {
            for (i = 1; i <= 19; i ++) {
                for (int j = 0; j < key_len; j ++) {
                    tempkey[j] = enckey[j] ^ (FX_BYTE)i;
                }
                CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len);
            }
        }
        pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32));
    }
    CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray);
    if (m_Revision < 3) {
        FX_BYTE tempbuf[32];
        FXSYS_memcpy32(tempbuf, defpasscode, 32);
        CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len);
        pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32));
    } else {
        FX_BYTE md5[100];
        CRYPT_MD5Start(md5);
        CRYPT_MD5Update(md5, defpasscode, 32);
        if (pIdArray) {
            CFX_ByteString id = pIdArray->GetString(0);
            CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength());
        }
        FX_BYTE digest[32];
        CRYPT_MD5Finish(md5, digest);
        CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len);
        FX_BYTE tempkey[32];
        for (int i = 1; i <= 19; i ++) {
            for (int j = 0; j < key_len; j ++) {
                tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i;
            }
            CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len);
        }
        CRYPT_MD5Generate(digest, 16, digest + 16);
        pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32));
    }
}