private Mono<Void> setBucketPolicy(String bucket, List<String> allowedReferrers) {
        BucketPolicyStatement.BucketPolicyStatementBuilder statementBuilder =
                BucketPolicyStatement.builder()
                        .sid("PublicRead")
                        .effect(BucketPolicyEffect.ALLOW)
                        .principal("*")
                        .action(List.of(BucketPolicyAction.GET_OBJECT))
                        .resource(List.of("arn:aws:s3:::"
                                + bucket
                                + "/*"));
        if (CollectionUtil.isNotEmpty(allowedReferrers)) {
            statementBuilder.conditions(Map.of(BucketPolicyConditionOperator.STRING_LIKE,
                    new BucketPolicyConditionCriteria()
                            .withCondition(BucketPolicyConditionKey.REFERER, allowedReferrers)));
        }
        BucketPolicy policy = BucketPolicy.builder()
                .version("2012-10-17")
                .statement(List.of(statementBuilder.build()))
                .build();
        String config = JsonUtil.writeAsString(policy);
        return PublisherUtil.fromFuture(() -> client.setBucketPolicy(SetBucketPolicyArgs.builder()
                .bucket(bucket)
                .config(config)
                .build()))
                .onErrorMap(t -> new RuntimeException(
                        "Failed to set the bucket policy ("
                                + StringUtil.sanitizeLatin1(config)
                                + ") to the bucket: \""
                                + bucket
                                + "\"",
                        t))
                .then();
    }
@implNote 1. We use HMAC(key, message) instead of a HASH(key + message) to avoid the length
          extension attack. To put simply, if a hacker knows the signature of the resource
          "1", and he can also know the signature of resource "12", "13", "123", and so on
          without knowledge of the key.
          <p>
          2. Use MD5 because its output size (128 bits) is small, and it is a 22-character
          Base62-encoded string.
turms-plugins/turms-plugin-minio/src/main/java/im/turms/plugin/minio/MinioStorageServiceProvider.java