webcrypto-liner icon indicating copy to clipboard operation
webcrypto-liner copied to clipboard

Doesn't work in Safari

Open borisreitman opened this issue 6 years ago • 10 comments

I cloned the project, installed webpack, and ran webpack that generated files in dist/ directory. However, when I try to run the example in examples/src/index.html on Safari, I get an error.

The first error I get is "unable to delete property" on line 3719:

3710 Object.defineProperty(exports, "__esModule", { value: true });
3711 var index_1 = __webpack_require__(6);
3712 var w = self;
3713 // Object.freeze(Math);
3714 // Object.freeze(Math.random);
3715 // Object.freeze((Math as any).imul);
3716 if (index_1.nativeCrypto) {
3717     Object.freeze(index_1.nativeCrypto.getRandomValues);
3718 }
3719 delete self.crypto;
3720 w.crypto = new index_1.Crypto();
3721 Object.freeze(w.crypto);
3722 exports.crypto = w.crypto;
3723 

When I actually try to use the sample, I get the error:

undefined is not an object (evaluating 'crypto.subtle.generateKey')

Safari version: Version 9.1.3 (11601.7.8) on a MacBook Pro, OSX version 10.11.6 (15G1004)

borisreitman avatar Dec 19 '17 23:12 borisreitman

Sounds like you didn't follow the steps in https://github.com/PeculiarVentures/webcrypto-liner#installation

Specifically if your going to run in a browser that doesn't support ES6 you need to be sure to convert to ES2015

rmhrisk avatar Dec 20 '17 00:12 rmhrisk

Ok, I now followed the steps, the error now occurs on a different line, but the error is the same "Unable to delete property".

2413    n.nativeCrypto && Object.freeze(n.nativeCrypto.getRandomValues), delete self.crypto, a.crypto = new n.Crypto, Object.freeze(a.crypto), r.crypto = a.crypto

Basically, if I would try to manually do: delete window.crypto I get the same error. It appears that this property is read-only in Safari. Doing the same in Google Chrome works and gives no errors.

borisreitman avatar Dec 20 '17 02:12 borisreitman

I tried this fix, and got past that error,

diff --git a/src/shim.ts b/src/shim.ts
index d136bde..06b6dc2 100644
--- a/src/shim.ts
+++ b/src/shim.ts
@@ -10,8 +10,12 @@ if (nativeCrypto) {
     Object.freeze(nativeCrypto.getRandomValues);
 }
 
-delete (self as any).crypto;
-w.crypto = new Crypto();
+try {
+  delete (self as any).crypto;
+  w.crypto = new Crypto();
+} catch(e){
+  w.crypto.subtle = new Crypto().subtle;
+}
 Object.freeze(w.crypto);
 
 export const crypto = w.crypto;

However, when I try to use the sample to "Sign", I get error from App.sign() call, that I tracked down to this line in file subtle.ts:

                if (!key.key) {
                    throw new LinerError("Cannot export native CryptoKey from JS implementation");
                }

borisreitman avatar Dec 20 '17 02:12 borisreitman

Works in Safari without code modification as we use it in several projects, ill have @microshine take a look when he gets online.

rmhrisk avatar Dec 20 '17 03:12 rmhrisk

Hi Ryan ,

Can you recommend something that I can use in Cordova to encrypt with AES-GCM on the mobile phone? Some Cordova plugin perhaps ?

Thanks , Boris

On 2017-12-19 at 7:27 PM, "Ryan Hurst" [email protected] wrote:

Works in Safari without code modification as we use it in several projects, ill have @microshine take a look when he gets online.

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/PeculiarVentures/webcrypto- liner/issues/44#issuecomment-352954831

borisreitman avatar Dec 20 '17 03:12 borisreitman

Boris,

I am not too familiar with cordova/phonegap but I understand you end up with JS also using this should work.

Ryan

rmhrisk avatar Dec 20 '17 03:12 rmhrisk

@borisreitman Could you try https://github.com/PeculiarVentures/webcrypto-liner/blob/master/dist/webcrypto-liner.lib.js? This variant of webcrypto-liner doesn't delete native crypto object. This script uses global liner variable which has own crypto object. We use webcrypto-liner.lib.js for Web Worker, because some browsers don't allow to remove native crypto

Example

<script src="https://peculiarventures.github.io/pv-webcrypto-tests/src/asmcrypto.js"></script>
<script src="webcrypto-liner.lib.js"></script>
liner.crypto.subtle.generateKey({name: "AES-GCM", length: 256}, false, ["encrypt"]).then((k) => {
  console.log(k);
})

microshine avatar Dec 20 '17 19:12 microshine

Yes, this version worked fine.

Quick question: does liner work in a browser that has no native window.crypto at all ?

borisreitman avatar Dec 20 '17 19:12 borisreitman

@borisreitman Yes, it does. You can use this script to do it. webcrypto-liner needs getRandomValues for key generation. So if you don't have crypto object you must implement your own getRandomValues

Example

function getRandomArbitrary(min, max)
{
    return self.Math.random() * (max - min) + min;
}

function getRandomValues(buffer)
{
    // TODO: seed random
    const buf = new Uint8Array(buffer.buffer);
    let i = 0;
	
    while(i < buf.length)
        buf[i++] = getRandomArbitrary(0, 255);
	
    return buffer;
}

if(!self.crypto) {
    self.crypto = { getRandomValues: getRandomValues };
    Object.freeze(self.crypto);
}

microshine avatar Dec 20 '17 20:12 microshine

For anyone else who may benefit from reading this thread, here's a tip on where to get native random numbers in Cordova.

var crypto = new AeroGear.Crypto();
crypto.getRandomValue();

https://github.com/aerogear/aerogear-cordova-crypto

EDIT: I just checked that both Android Webview and iOS Safari (and probably the iOS Webview) have window.crypto.getRandomValues() and the whole window.crypto.subtle suite. Someone has reported on StackOverflow that Android has no subtle, but it was his error. It's there, as long as user is using https:// to browse a website. And, it is there in the Cordova webview.

borisreitman avatar Dec 20 '17 21:12 borisreitman