4

I am working with Cordova and forge library and browser's Web Crypto API to perform sign and importKey operations. Nonetheless, Web Crypto API on Android device only offers crypto.getRandomValues() and SubtleCrypto is undefined (crypto.subtle). So I thought adding Web Crypto API shrim and its dependancy Promiz would fix this reference missing, but nothing has changed. Any idea please?

Debugging on PC in Chrome 52.0.2743.116 offers full Web Crypto API, however on Android device with Chrome version 52.0.2743.98 with Android 4.4.4. the Web API is limited only to crypto.getRandomValues().

I'am basically rewriting answer from How to load a PKCS#12 Digital Certificate with Javascript WebCrypto API

Code example:

Inside index.html

<script src="lib/promiz.min.js"></script>
<script src="lib/webcrypto-shim.js"></script>

Inside javascript file

//working with forge without issue
var pkcs12Der = forge.util.decode64(pk);
var pkcs12Asn1 = forge.asn1.fromDer(pkcs12Der);
var pkcs12 = forge.pkcs12.pkcs12FromAsn1(pkcs12Asn1, false, "password");
console.log(pkcs12);

privateKey = null;
// load keypair and cert chain from safe content(s) 
for (var sci = 0; sci < pkcs12.safeContents.length; ++sci) {
    var safeContents = pkcs12.safeContents[sci];

    for (var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) {
        var safeBag = safeContents.safeBags[sbi];

        // this bag has a private key
        if (safeBag.type === forge.pki.oids.keyBag) {
            //Found plain private key
            privateKey = safeBag.key;
        } else if (safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
            // found encrypted private key
            privateKey = safeBag.key;
        } else if (safeBag.type === forge.pki.oids.certBag) {
            // this bag has a certificate...        
        }
    }
}

//function for importingKey 
function _importCryptoKeyPkcs8(privateKey, extractable) {
    var privateKeyInfoDerBuff = _privateKeyToPkcs8(privateKey);

    //import key will not work due to missing reference crypto.subtle
    return window.crypto.subtle.importKey(
        'pkcs8',
        privateKeyInfoDerBuff, {
            name: "RSASSA-PKCS1-v1_5",
            hash: {
                name: "SHA-256"
            }
        },
        extractable, ["sign"]);

}

_importCryptoKeyPkcs8(privateKey, true).
then(function(cryptoKey) {
   //sign will not work due to missing reference crypto.subtle
    window.crypto.subtle.sign({
                name: "RSASSA-PKCS1-v1_5"
            },
            cryptoKey,
            digestToSignBuf)
        .then(function(signature2) {

        });
});
Community
  • 1
  • 1
Marek
  • 3,555
  • 17
  • 74
  • 123
  • 1
    Can you show us sample code ? Especially with the webcrypto-shim library. – e666 Aug 21 '16 at 10:59
  • @e666 Added code sample. It fails to correctly reference the window.crypto.subtle which is undefined. – Marek Aug 21 '16 at 11:17
  • 1
    Isn't forge able to do this completely? Are you sure that you need `window.crypto` at all? – Artjom B. Aug 21 '16 at 16:03
  • I think WebCryptographyApi is not available of Android WebView, but why do you need WebCrypto or forge? Android has native support for pkcs12 files, signature and verification. Even It has native key storage since version 18 https://developer.android.com/training/articles/keystore.html. I understand that the downside is that you need a native component to connect from Cordova. Alternatively, I think you could use only forge, as suggest @ArtjomB. – pedrofb Aug 21 '16 at 20:58
  • 1
    One of the ideas behind WebCrypto API in browsers is to let you have secure cryptographic computation using Javascript in browsers. By using shims and pollyfills you just make your app work but with less security. – Emad Van Ben Nov 07 '16 at 22:01

2 Answers2

3

SubtleCrypto is supposed to be undefined in insecure contexts. I guess you were using http protocol. Switch to https to solve the issue. I once wasted 4 hours of development time because of this.

Edit : If SubtleCrypto is undefined and you called some function on it you'd expect there'd be an error message but no there won't by any errors , warnings or anything.Nothing. It would be like calling an empty function. A real pain when you're debugging.

Shiva Teja
  • 417
  • 4
  • 16
0

I had also a lot of problems with the Web Crypto API in a cordova app and didn't find a solution for importing or saving the keys.

But what I found yesterday is this JS-Library:

https://github.com/wwwtyro/cryptico

Maybe you can change your code and can use it.

Joerg
  • 3,102
  • 2
  • 24
  • 30