Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 51 additions & 51 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ PODS:
- glog
- hermes-engine
- NitroModules
- OpenSSL-Universal
- OpenSSL-Universal (= 3.3.3001)
- RCT-Folly (= 2024.10.14.00)
- RCTRequired
- RCTTypeSafety
Expand Down Expand Up @@ -1974,72 +1974,72 @@ SPEC CHECKSUMS:
fmt: 01b82d4ca6470831d1cc0852a1af644be019e8f6
glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a
hermes-engine: 9e868dc7be781364296d6ee2f56d0c1a9ef0bb11
NitroModules: fdc6fcf8f397091615951004ae81022b759e27bc
NitroModules: 161f76b119543ff2b097c17cc629ea1ca39e4279
OpenSSL-Universal: 6082b0bf950e5636fe0d78def171184e2b3899c2
QuickCrypto: 1027d2c8c624b7534dcd1df7284954d26246d517
RCT-Folly: ea9d9256ba7f9322ef911169a9f696e5857b9e17
QuickCrypto: a0b0541abc0b2594e228fe753bb25458b450afab
RCT-Folly: 7b4f73a92ad9571b9dbdb05bb30fad927fa971e1
RCTDeprecation: ebe712bb05077934b16c6bf25228bdec34b64f83
RCTRequired: ca91e5dd26b64f577b528044c962baf171c6b716
RCTTypeSafety: e7678bd60850ca5a41df9b8dc7154638cb66871f
React: 4641770499c39f45d4e7cde1eba30e081f9d8a3d
React-callinvoker: 4bef67b5c7f3f68db5929ab6a4d44b8a002998ea
React-Core: a68cea3e762814e60ecc3fa521c7f14c36c99245
React-CoreModules: d81b1eaf8066add66299bab9d23c9f00c9484c7c
React-cxxreact: 984f8b1feeca37181d4e95301fcd6f5f6501c6ab
React-Core: 0a06707a0b34982efc4a556aff5dae4b22863455
React-CoreModules: 907334e94314189c2e5eed4877f3efe7b26d85b0
React-cxxreact: 3a1d5e8f4faa5e09be26614e9c8bbcae8d11b73d
React-debug: 817160c07dc8d24d020fbd1eac7b3558ffc08964
React-defaultsnativemodule: 18a684542f82ce1897552a1c4b847be414c9566e
React-domnativemodule: 90bdd4ec3ab38c47cfc3461c1e9283a8507d613f
React-Fabric: f6dade7007533daeb785ba5925039d83f343be4b
React-FabricComponents: b0655cc3e1b5ae12a4a1119aa7d8308f0ad33520
React-FabricImage: 9b157c4c01ac2bf433f834f0e1e5fe234113a576
React-defaultsnativemodule: 814830ccbc3fb08d67d0190e63b179ee4098c67b
React-domnativemodule: 270acf94bd0960b026bc3bfb327e703665d27fb4
React-Fabric: 64586dc191fc1c170372a638b8e722e4f1d0a09b
React-FabricComponents: b0ebd032387468ea700574c581b139f57a7497fb
React-FabricImage: 81f0e0794caf25ad1224fa406d288fbc1986607f
React-featureflags: f2792b067a351d86fdc7bec23db3b9a2f2c8d26c
React-featureflagsnativemodule: 742a8325b3c821d2a1ca13a6d2a0fc72d04555e0
React-graphics: 68969e4e49d73f89da7abef4116c9b5f466aa121
React-hermes: ac0bcba26a5d288ebc99b500e1097da2d0297ddf
React-idlecallbacksnativemodule: d61d9c9816131bf70d3d80cd04889fc625ee523f
React-ImageManager: e906eec93a9eb6102a06576b89d48d80a4683020
React-jserrorhandler: ac5dde01104ff444e043cad8f574ca02756e20d6
React-jsi: 496fa2b9d63b726aeb07d0ac800064617d71211d
React-jsiexecutor: dd22ab48371b80f37a0a30d0e8915b6d0f43a893
React-jsinspector: 4629ac376f5765e684d19064f2093e55c97fd086
React-jsitracing: 7a1c9cd484248870cf660733cd3b8114d54c035f
React-logger: c4052eb941cca9a097ef01b59543a656dc088559
React-Mapbuffer: 33546a3ebefbccb8770c33a1f8a5554fa96a54de
React-microtasksnativemodule: d80ff86c8902872d397d9622f1a97aadcc12cead
react-native-quick-base64: 17dc4b8daee50e680d5f57cc3ee6773b6ee0110a
react-native-safe-area-context: 60695fadbcee6ab51b28b835abb10ea983dbe181
React-featureflagsnativemodule: 0d7091ae344d6160c0557048e127897654a5c00f
React-graphics: cbebe910e4a15b65b0bff94a4d3ed278894d6386
React-hermes: ec18c10f5a69d49fb9b5e17ae95494e9ea13d4d3
React-idlecallbacksnativemodule: 6b84add48971da9c40403bd1860d4896462590f2
React-ImageManager: f2a4c01c2ccb2193e60a20c135da74c7ca4d36f2
React-jserrorhandler: 61d205b5a7cbc57fed3371dd7eed48c97f49fc64
React-jsi: 95f7676103137861b79b0f319467627bcfa629ee
React-jsiexecutor: 41e0fe87cda9ea3970ffb872ef10f1ff8dbd1932
React-jsinspector: 15578208796723e5c6f39069b6e8bf36863ef6e2
React-jsitracing: 3758cdb155ea7711f0e77952572ea62d90c69f0b
React-logger: dbca7bdfd4aa5ef69431362bde6b36d49403cb20
React-Mapbuffer: 6efad4a606c1fae7e4a93385ee096681ef0300dc
React-microtasksnativemodule: a645237a841d733861c70b69908ab4a1707b52ad
react-native-quick-base64: 5c67f3f20cf7878e9deb449188b432de897d212c
react-native-safe-area-context: 511649fbcdb7b88d29660aa5c0936b3cd03c935d
React-nativeconfig: 8efdb1ef1e9158c77098a93085438f7e7b463678
React-NativeModulesApple: cebca2e5320a3d66e123cade23bd90a167ffce5e
React-perflogger: 72e653eb3aba9122f9e57cf012d22d2486f33358
React-performancetimeline: cd6a9374a72001165995d2ab632f672df04076dc
React-NativeModulesApple: 958d4f6c5c2ace4c0f427cf7ef82e28ae6538a22
React-perflogger: 9b4f13c0afe56bc7b4a0e93ec74b1150421ee22d
React-performancetimeline: 359db1cb889aa0282fafc5838331b0987c4915a9
React-RCTActionSheet: aacf2375084dea6e7c221f4a727e579f732ff342
React-RCTAnimation: 395ab53fd064dff81507c15efb781c8684d9a585
React-RCTAppDelegate: 345a6f1b82abc578437df0ce7e9c48740eca827c
React-RCTBlob: 13311e554c1a367de063c10ee7c5e6573b2dd1d6
React-RCTFabric: 007b1a98201cc49b5bc6e1417d7fe3f6fc6e2b78
React-RCTImage: 1b1f914bcc12187c49ba5d949dac38c2eb9f5cc8
React-RCTLinking: 4ac7c42beb65e36fba0376f3498f3cd8dd0be7fa
React-RCTNetwork: 938902773add4381e84426a7aa17a2414f5f94f7
React-RCTSettings: e848f1ba17a7a18479cf5a31d28145f567da8223
React-RCTText: 7e98fafdde7d29e888b80f0b35544e0cb07913cf
React-RCTVibration: cd7d80affd97dc7afa62f9acd491419558b64b78
React-RCTAnimation: d8c82deebebe3aaf7a843affac1b57cb2dc073d4
React-RCTAppDelegate: 1774aa421a29a41a704ecaf789811ef73c4634b6
React-RCTBlob: 70a58c11a6a3500d1a12f2e51ca4f6c99babcff8
React-RCTFabric: 731cda82aed592aacce2d32ead69d78cde5d9274
React-RCTImage: 5e9d655ba6a790c31e3176016f9b47fd0978fbf0
React-RCTLinking: 2a48338252805091f7521eaf92687206401bdf2a
React-RCTNetwork: 0c1282b377257f6b1c81934f72d8a1d0c010e4c3
React-RCTSettings: f757b679a74e5962be64ea08d7865a7debd67b40
React-RCTText: e7d20c490b407d3b4a2daa48db4bcd8ec1032af2
React-RCTVibration: 8228e37144ca3122a91f1de16ba8e0707159cfec
React-rendererconsistency: b4917053ecbaa91469c67a4319701c9dc0d40be6
React-rendererdebug: aa181c36dd6cf5b35511d1ed875d6638fd38f0ec
React-rendererdebug: 81becbc8852b38d9b1b68672aa504556481330d5
React-rncore: 120d21715c9b4ba8f798bffe986cb769b988dd74
React-RuntimeApple: d033becbbd1eba6f9f6e3af6f1893030ce203edd
React-RuntimeCore: 38af280bb678e66ba000a3c3d42920b2a138eebb
React-RuntimeApple: 52ed0e9e84a7c2607a901149fb13599a3c057655
React-RuntimeCore: ca6189d2e53d86db826e2673fe8af6571b8be157
React-runtimeexecutor: 877596f82f5632d073e121cba2d2084b76a76899
React-RuntimeHermes: 37aad735ff21ca6de2d8450a96de1afe9f86c385
React-runtimescheduler: 8ec34cc885281a34696ea16c4fd86892d631f38d
React-RuntimeHermes: 3b752dc5d8a1661c9d1687391d6d96acfa385549
React-runtimescheduler: 8321bb09175ace2a4f0b3e3834637eb85bf42ebe
React-timing: 331cbf9f2668c67faddfd2e46bb7f41cbd9320b9
React-utils: ed818f19ab445000d6b5c4efa9d462449326cc9f
ReactCodegen: b53cf388615e972ad884b0bb3a5cc5669dba3622
ReactCommon: 300d8d9c5cb1a6cd79a67cf5d8f91e4d477195f9
RNScreens: b31a78e0ad400e1ebca64016a0d3f45cbde507eb
RNVectorIcons: 5470dab316a41f06439f84a15a51416fb7f6844d
React-utils: 54df9ada708578c8ad40d92895d6fed03e0e8a9e
ReactCodegen: 90cd5a1af9dc764219d39bc39be3306ac084c4dc
ReactCommon: bfd3600989d79bc3acbe7704161b171a1480b9fd
RNScreens: 2a0cfe88d6323d5f4e6ac3e8d033ba452724631b
RNVectorIcons: abbbb380d83c3464522fdec4ad29f33759041fdb
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: feb4910aba9742cfedc059e2b2902e22ffe9954a

PODFILE CHECKSUM: 63c4c1ca9d3ee6394f468b17e19efd3e548b5357

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
36 changes: 36 additions & 0 deletions example/src/tests/hash/hash_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,42 @@ test(SUITE, 'createHash with null algorithm', () => {
}).to.throw(/Algorithm must be a non-empty string/);
});

test(SUITE, 'check openssl version', () => {
expect(() => {
// Create a hash to trigger OpenSSL initialization
const hash = createHash('sha256');

// Get OpenSSL version directly from the hash object
const version = hash.getOpenSSLVersion();
console.log('OpenSSL Version:', version);
}).to.not.throw();
});

test(SUITE, 'keccak256 function using provider-aware API', () => {
const { keccak256 } = require('react-native-quick-crypto');

// Test with a simple string
const result1 = keccak256('test');
expect(result1.toString('hex')).to.equal('9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658');

// Test with empty string
const result2 = keccak256('');
expect(result2.toString('hex')).to.equal('c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470');

// Test with Buffer
const result3 = keccak256(Buffer.from('hello world'));
expect(result3.toString('hex')).to.equal('47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad');

// Verify the result is 32 bytes (256 bits)
expect(result1.length).to.equal(32);
expect(result2.length).to.equal(32);
expect(result3.length).to.equal(32);

// Test that it's different from SHA3-256 (they should be different)
const sha3Hash = createHash('SHA3-256').update('test').digest();
expect(result1.toString('hex')).to.not.equal(sha3Hash.toString('hex'));
});

// test hashing
const a0 = createHash('md5').update('Test123').digest('latin1');
const a1 = createHash('sha1').update('Test123').digest('hex');
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-quick-crypto/QuickCrypto.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ Pod::Spec.new do |s|

s.dependency "React-jsi"
s.dependency "React-callinvoker"
s.dependency "OpenSSL-Universal"
s.dependency "OpenSSL-Universal", "3.3.3001"
install_modules_dependencies(s)
end
41 changes: 41 additions & 0 deletions packages/react-native-quick-crypto/cpp/hash/HybridHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <memory>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/opensslv.h>
#include <optional>
#include <string>
#include <vector>
Expand Down Expand Up @@ -148,4 +149,44 @@ void HybridHash::setParams() {
}
}

std::string HybridHash::getOpenSSLVersion() {
return OpenSSL_version(OPENSSL_VERSION);
}

std::shared_ptr<ArrayBuffer> HybridHash::keccak256(const std::shared_ptr<ArrayBuffer>& data) {
// 1. Obtain the Keccak-256 message-digest implementation from any loaded provider.
const EVP_MD* md = EVP_MD_fetch(nullptr, "KECCAK-256", nullptr);
if (!md) {
throw std::runtime_error("KECCAK-256 digest not available in the current OpenSSL build (provider not loaded?)");
}

// 2. Create and initialise a digest context.
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
if (!ctx) {
throw std::runtime_error("Failed to allocate EVP_MD_CTX");
}
auto ctx_guard = std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(ctx, &EVP_MD_CTX_free);

if (EVP_DigestInit_ex(ctx, md, nullptr) != 1) {
throw std::runtime_error("Failed to initialise KECCAK-256 digest");
}

// 3. Feed the data.
if (EVP_DigestUpdate(ctx, data->data(), data->size()) != 1) {
throw std::runtime_error("Failed to update KECCAK-256 digest");
}

// 4. Finalise and collect the output.
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int out_len = 0;
if (EVP_DigestFinal_ex(ctx, hash, &out_len) != 1) {
throw std::runtime_error("Failed to finalise KECCAK-256 digest");
}

// 5. Move the result into a managed ArrayBuffer.
unsigned char* out_buf = new unsigned char[out_len];
std::memcpy(out_buf, hash, out_len);
return std::make_shared<NativeArrayBuffer>(out_buf, out_len, [out_buf]() { delete[] out_buf; });
}

} // namespace margelo::nitro::crypto
2 changes: 2 additions & 0 deletions packages/react-native-quick-crypto/cpp/hash/HybridHash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class HybridHash : public HybridHashSpec {
std::shared_ptr<ArrayBuffer> digest(const std::optional<std::string>& encoding = std::nullopt) override;
std::shared_ptr<margelo::nitro::crypto::HybridHashSpec> copy(const std::optional<double> outputLength) override;
std::vector<std::string> getSupportedHashAlgorithms() override;
std::string getOpenSSLVersion() override;
std::shared_ptr<ArrayBuffer> keccak256(const std::shared_ptr<ArrayBuffer>& data) override;

private:
// Methods
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions packages/react-native-quick-crypto/src/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@ class HashUtils {
public static getSupportedHashAlgorithms(): string[] {
return this.native.getSupportedHashAlgorithms();
}
public static keccak256(data: BinaryLike): Buffer {
const nativeDigest = this.native.keccak256(binaryLikeToArrayBuffer(data, 'utf8'));
return Buffer.from(nativeDigest);
}
}

export function getHashes() {
return HashUtils.getSupportedHashAlgorithms();
}

export function keccak256(data: BinaryLike): Buffer {
return HashUtils.keccak256(data);
}

interface HashOptions extends TransformOptions {
/**
* For XOF hash functions such as `shake256`, the
Expand Down Expand Up @@ -157,6 +165,25 @@ class Hash extends Stream.Transform {
return hash;
}

/**
* Returns the OpenSSL version string
* @since v1.0.0
*/
getOpenSSLVersion(): string {
return this.native.getOpenSSLVersion();
}

/**
* Computes KECCAK-256 hash of the provided data using OpenSSL's provider-aware API
* @since v1.0.0
* @param data The data to hash
* @returns Buffer containing the KECCAK-256 hash
*/
keccak256(data: BinaryLike): Buffer {
const nativeDigest = this.native.keccak256(binaryLikeToArrayBuffer(data, 'utf8'));
return Buffer.from(nativeDigest);
}

// stream interface
_transform(
chunk: BinaryLike,
Expand Down Expand Up @@ -205,4 +232,5 @@ export function createHash(algorithm: string, options?: HashOptions): Hash {
export const hashExports = {
createHash,
getHashes,
keccak256,
};
2 changes: 2 additions & 0 deletions packages/react-native-quick-crypto/src/specs/hash.nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ export interface Hash extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
digest(encoding?: string): ArrayBuffer;
copy(outputLength?: number): Hash;
getSupportedHashAlgorithms(): string[];
getOpenSSLVersion(): string;
keccak256(data: ArrayBuffer): ArrayBuffer;
}
Loading