Safari WebCrypto API RSA-OAEP encryption

喜夏-厌秋 提交于 2019-12-11 03:48:39

问题


I have the following code to test WebCrypto API. It works in Firefox and Chrome and I am trying to make it work in Safari.

 function ab2str(buf) {
      return String.fromCharCode.apply(null, new Uint16Array(buf));
    }

//converts a forge 0.6.x string of bytes to an ArrayBuffer
function str2ab(str) {
  var b = new ArrayBuffer(str.length);
  var view = new Uint8Array(b);
  for(var i = 0; i < str.length; ++i) {
    view[i] = str.charCodeAt(i);
  }
  return b;
}


function _arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}

var pubKey;
var privKey;

var s_pubKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5tieEkcDAqAp/baSmNIdg5ezJMcWJX63+hM/DQolgKtw9Dvc0c8GRUqK2r/idZ1iXJzOjWQ3KIFIzmgTRHOKe3aPgJADdZ2vyAqu2woKtsgQ8nTcDYI86dmyfYsHFbgbSn/qeoE8WEzwyT3OoGgn54zoMuQmUmLbGaJYY2XN5bxwqxsRJSoXetBu9o1G9Wy4V1fdxwjRtaO/2FrZfkLp/P5Tc5Hk1Ev7PIPrkRhrl/7lF4JblVRG5m90aeviErvFIN0LdlqiY90UaQY3gyTsylrheTlqRq6yyzKf3dWnF78+CeAqppsOMI+WHURThNLkN56EOTX6TaBrG6f2XjxeqQIDAQAB";

var cripto= window.crypto || window.msCrypto;
var subtle= cripto.subtle || window.crypto.webkitSubtle;

subtle.generateKey(
        {
            name: "RSA-OAEP",
            modulusLength: 2048, //can be 1024, 2048, or 4096
            publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
            hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
        },
        true, //whether the key is extractable (i.e. can be used in exportKey)
        ["encrypt", "decrypt"] //must contain both "encrypt" and "decrypt"
    )
    .then(function(key){
        //returns a keypair object
        //console.log(key);
        //console.log(key.publicKey);
        //console.log(key.privateKey);
        subtle.exportKey(
                "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
                key.publicKey //can be a publicKey or privateKey, as long as extractable was true
            )
            .then(function(keydata){
                //returns the exported key data

                console.log("publicKey:"+_arrayBufferToBase64(keydata));
                subtle.exportKey(
                        "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
                        key.privateKey //can be a publicKey or privateKey, as long as extractable was true
                    )
                    .then(function(keydata){
                        //returns the exported key data

                        console.log("privateKey:"+_arrayBufferToBase64(keydata));
                    });

                subtle.importKey(                       
                        "jwk", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
                        keydata,
                        {   //these are the algorithm options
                            name: "RSA-OAEP",
                            hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
                        },
                        false, //whether the key is extractable (i.e. can be used in exportKey)
                        ["encrypt"] //"encrypt" for public key import, "decrypt" for private key imports
                    )
                    .then(function(publicKey){
                        //returns a publicKey (or privateKey if you are importing a private key)
                        console.log(publicKey);

                        subtle.encrypt(
                                {
                                    name: "RSA-OAEP",
                                    //label: Uint8Array([...]) //optional
                                },
                                publicKey, //from generateKey or importKey above
                                str2ab("hola mundo") //ArrayBuffer of data you want to encrypt
                            )
                            .then(function(encrypted){
                                //returns an ArrayBuffer containing the encrypted data
                                //console.log(new Uint8Array(encrypted));
                                console.log("enc: "+_arrayBufferToBase64(encrypted));
                            })
                            .catch(function(err){
                                console.error(err);
                            });
                    })

            })

    })
    .catch(function(err){
        console.error(err);
    });

The problem is that subtle.encrypt apparently isn't executed. Neither console.log nor console.error is called. Any clue what is happening? The previous line "console.log(publicKey);" works fine.


回答1:


Current versions of Safari, Safari Technology Preview, and WebKit do not support RSA-OAEP-256. They only support the older RSA-OAEP with SHA-1:

https://bugs.webkit.org/show_bug.cgi?id=151308




回答2:


After your 'generateKey' call, are key.publicKey and key.privateKey actually CryptoKey objects? In my tinkering with Safari (on iPad) they just appear to be Objects... and when I call 'exportKey' I get a TypeError being thrown

p.s. Nevermind, I was using 'RSASSA-PKCS1-v1_5', not 'RSA-OAEP'.




回答3:


There are currently a number of problems with the Safari implementation of WebCrypto as well as the Edge implementation. This is complicated by the algorithm support differences between browsers.

You can explore what is supported by a given browser by visiting: https://peculiarventures.github.io/pv-webcrypto-tests/

Given these difference, we implemented this library that masks many of the differences and adds a few algorithms (optionally) to make them interop : https://github.com/PeculiarVentures/webcrypto-liner/blob/master/BrowserSupport.md

In the case of Safari they only support the following with RSA-OAEP:

  • RSA-OAEP mod:2048 pubExp:3 /w SHA1 format:jwk
  • RSA-OAEP mod:2048 pubExp:65535 /w SHA1 format:jwk

If you change: hash: {name: "SHA-256"}

to: hash: {name: "SHA-1"}

I suspect this will work.



来源:https://stackoverflow.com/questions/31798241/safari-webcrypto-api-rsa-oaep-encryption

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!