diff --git a/lib/api/apiUtils/integrity/validateChecksums.js b/lib/api/apiUtils/integrity/validateChecksums.js index 22f5f0ca40..1a0272440e 100644 --- a/lib/api/apiUtils/integrity/validateChecksums.js +++ b/lib/api/apiUtils/integrity/validateChecksums.js @@ -1,6 +1,6 @@ const crypto = require('crypto'); -const { Crc32 } = require('@aws-crypto/crc32'); -const { Crc32c } = require('@aws-crypto/crc32c'); +// Native hardware-accelerated, faster than pure-JS @aws-crypto/crc32{,c} +const { crc32: crtCrc32, crc32c: crtCrc32c } = require('aws-crt').checksums; const { CrtCrc64Nvme } = require('@aws-sdk/crc64-nvme-crt'); const { errors: ArsenalErrors, errorInstances } = require('arsenal'); const { config } = require('../../../Config'); @@ -127,6 +127,21 @@ function uint32ToBase64(num) { return buf.toString('base64'); } +class NativeCrc { + constructor(hashFunc) { + this.hashFunc = hashFunc; + this.crcValue = 0; + } + update(data) { + const input = Buffer.isBuffer(data) ? data : Buffer.from(data); + this.crcValue = this.hashFunc(input, this.crcValue) >>> 0; + return this; + } + digest() { + return this.crcValue >>> 0; + } +} + const algorithms = Object.freeze({ crc64nvme: { xmlTag: 'ChecksumCRC64NVME', @@ -148,24 +163,24 @@ const algorithms = Object.freeze({ xmlTag: 'ChecksumCRC32', digest: data => { const input = Buffer.isBuffer(data) ? data : Buffer.from(data); - return uint32ToBase64(new Crc32().update(input).digest() >>> 0); // >>> 0 coerce number to uint32 + return uint32ToBase64(crtCrc32(input, 0) >>> 0); // >>> 0 coerce number to uint32 }, digestFromHash: hash => { const result = hash.digest(); return uint32ToBase64(result >>> 0); }, isValidDigest: expected => typeof expected === 'string' && expected.length === 8 && base64Regex.test(expected), - createHash: () => new Crc32(), + createHash: () => new NativeCrc(crtCrc32), }, crc32c: { xmlTag: 'ChecksumCRC32C', digest: data => { const input = Buffer.isBuffer(data) ? data : Buffer.from(data); - return uint32ToBase64(new Crc32c().update(input).digest() >>> 0); // >>> 0 coerce number to uint32 + return uint32ToBase64(crtCrc32c(input, 0) >>> 0); // >>> 0 coerce number to uint32 }, digestFromHash: hash => uint32ToBase64(hash.digest() >>> 0), isValidDigest: expected => typeof expected === 'string' && expected.length === 8 && base64Regex.test(expected), - createHash: () => new Crc32c(), + createHash: () => new NativeCrc(crtCrc32c), }, sha1: { xmlTag: 'ChecksumSHA1', diff --git a/package.json b/package.json index c0e3dfaf94..a7f3df8652 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zenko/cloudserver", - "version": "9.4.0-preview.4", + "version": "9.4.0-preview.5", "description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol", "main": "index.js", "engines": { @@ -19,8 +19,6 @@ }, "homepage": "https://github.com/scality/S3#readme", "dependencies": { - "@aws-crypto/crc32": "^5.2.0", - "@aws-crypto/crc32c": "^5.2.0", "@aws-sdk/client-iam": "^3.930.0", "@aws-sdk/client-s3": "^3.1013.0", "@aws-sdk/client-sts": "^3.930.0", @@ -39,6 +37,7 @@ "@smithy/node-http-handler": "^3.0.0", "arsenal": "git+https://github.com/scality/arsenal#8.5.6", "async": "2.6.4", + "aws-crt": "^1.24.0", "bucketclient": "scality/bucketclient#8.2.7", "bufferutil": "^4.0.8", "commander": "^12.1.0",