diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 5feaa21a..feed0fbe 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -30,7 +30,7 @@ jobs:
   node:
     strategy:
       matrix:
-        node-version: [14.x, 16.x, 18.x]
+        node-version: [14.x, 16.x, 18.x, 20.x]
         # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
 
     name: Node ${{ matrix.node-version }}
diff --git a/src/crypto/mode/gcm.js b/src/crypto/mode/gcm.js
index 5751ad67..25c7a059 100644
--- a/src/crypto/mode/gcm.js
+++ b/src/crypto/mode/gcm.js
@@ -47,6 +47,25 @@ async function GCM(cipher, key) {
     throw new Error('GCM mode supports only AES cipher');
   }
 
+  if (util.getNodeCrypto()) { // Node crypto library
+    return {
+      encrypt: async function(pt, iv, adata = new Uint8Array()) {
+        const en = new nodeCrypto.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
+        en.setAAD(adata);
+        const ct = Buffer.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext
+        return new Uint8Array(ct);
+      },
+
+      decrypt: async function(ct, iv, adata = new Uint8Array()) {
+        const de = new nodeCrypto.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
+        de.setAAD(adata);
+        de.setAuthTag(ct.slice(ct.length - tagLength, ct.length)); // read auth tag at end of ciphertext
+        const pt = Buffer.concat([de.update(ct.slice(0, ct.length - tagLength)), de.final()]);
+        return new Uint8Array(pt);
+      }
+    };
+  }
+
   if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support
     const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']);
 
@@ -69,25 +88,6 @@ async function GCM(cipher, key) {
     };
   }
 
-  if (util.getNodeCrypto()) { // Node crypto library
-    return {
-      encrypt: async function(pt, iv, adata = new Uint8Array()) {
-        const en = new nodeCrypto.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
-        en.setAAD(adata);
-        const ct = Buffer.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext
-        return new Uint8Array(ct);
-      },
-
-      decrypt: async function(ct, iv, adata = new Uint8Array()) {
-        const de = new nodeCrypto.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv);
-        de.setAAD(adata);
-        de.setAuthTag(ct.slice(ct.length - tagLength, ct.length)); // read auth tag at end of ciphertext
-        const pt = Buffer.concat([de.update(ct.slice(0, ct.length - tagLength)), de.final()]);
-        return new Uint8Array(pt);
-      }
-    };
-  }
-
   return {
     encrypt: async function(pt, iv, adata) {
       return AES_GCM.encrypt(pt, key, iv, adata);
diff --git a/src/crypto/random.js b/src/crypto/random.js
index 9d3afe80..022bb4aa 100644
--- a/src/crypto/random.js
+++ b/src/crypto/random.js
@@ -33,11 +33,11 @@ const nodeCrypto = util.getNodeCrypto();
  */
 export function getRandomBytes(length) {
   const buf = new Uint8Array(length);
-  if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
-    crypto.getRandomValues(buf);
-  } else if (nodeCrypto) {
+  if (nodeCrypto) {
     const bytes = nodeCrypto.randomBytes(buf.length);
     buf.set(bytes);
+  } else if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
+    crypto.getRandomValues(buf);
   } else {
     throw new Error('No secure random number generator available.');
   }
diff --git a/test/crypto/crypto.js b/test/crypto/crypto.js
index 68009ec3..8c5417bc 100644
--- a/test/crypto/crypto.js
+++ b/test/crypto/crypto.js
@@ -255,7 +255,7 @@ module.exports = () => describe('API functional testing', function() {
       // test using webCrypto
       const sinonSandbox = sandbox.create();
       const webCrypto = util.getWebCrypto();
-      if (webCrypto) {
+      if (webCrypto && !util.getNodeCrypto()) {
         const webCryptoSpy = sinonSandbox.spy(webCrypto, 'encrypt');
         try {
           await testCFB('12345678901234567890123456789012345678901234567890', { ...openpgp.config, minBytesForWebCrypto: 0 });
diff --git a/test/crypto/gcm.js b/test/crypto/gcm.js
index 9896e3c4..d3b0f01b 100644
--- a/test/crypto/gcm.js
+++ b/test/crypto/gcm.js
@@ -47,8 +47,8 @@ module.exports = () => describe('Symmetric AES-GCM (experimental)', function() {
         const key = crypto.generateSessionKey(algo);
         const iv = crypto.random.getRandomBytes(crypto.mode.gcm.ivLength);
 
-        const nativeEncryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'encrypt') : sinonSandbox.spy(nodeCrypto, 'createCipheriv');
-        const nativeDecryptSpy = webCrypto ? sinonSandbox.spy(webCrypto, 'decrypt') : sinonSandbox.spy(nodeCrypto, 'createDecipheriv');
+        const nativeEncryptSpy = nodeCrypto ? sinonSandbox.spy(nodeCrypto, 'createCipheriv') : sinonSandbox.spy(webCrypto, 'encrypt');
+        const nativeDecryptSpy = nodeCrypto ? sinonSandbox.spy(nodeCrypto, 'createDecipheriv') : sinonSandbox.spy(webCrypto, 'decrypt');
 
         nativeEncrypt || disableNative();
         let modeInstance = await crypto.mode.gcm(algo, key);
diff --git a/test/general/packet.js b/test/general/packet.js
index 251e2e25..212e874f 100644
--- a/test/general/packet.js
+++ b/test/general/packet.js
@@ -202,7 +202,7 @@ module.exports = () => describe('Packet', function() {
 
   it('Sym. encrypted AEAD protected packet is encrypted in parallel (AEAD, GCM)', async function() {
     const webCrypto = util.getWebCrypto();
-    if (!webCrypto) return;
+    if (!webCrypto || util.getNodeCrypto()) return;
     const encryptStub = cryptStub(webCrypto, 'encrypt');
     const decryptStub = cryptStub(webCrypto, 'decrypt');