2

I am trying to get access to a public key by using export key which is described here. I have the following code:

window.crypto.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 be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
        )
            .then(function(key){
                //returns a keypair object
                console.log(key);
                console.log(key.publicKey);
                console.log(key.privateKey);

        window.crypto.subtle.exportKey("spki",key.publicKey)
            .then(function(keydata){
                //returns the exported key data
                console.log(keydata);
                document.getElementById("key").innerHTML = String(key.publicKey)
            })
            .catch(function(err){
                console.error(err);
            });
    })

I would like to view the public key and for example set it to a HTML element, at the moment the HTML element is being set to [object CryptoKey]. How can I access the public key directly?

Thanks

EDIT:

window.crypto.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 be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
        )
            .then(function(key){
                //returns a keypair object
                console.log(key);
                console.log(key.publicKey);
                console.log(key.privateKey);

                window.crypto.subtle.exportKey("spki",key.publicKey)
                    .then(function(keydata){
                        //returns the exported key data
                        console.log(keydata);
                        var  publicKeyB64 = ab2str(keydata);
                        document.getElementById("key").innerHTML = publicKeyB64;

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




        function ab2str( 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 );
        }
Future
  • 191
  • 2
  • 13

1 Answers1

2

keydata is an ArrayBuffer which contains the public key exported as DER format. Since DER is binary it is needed to encode the result as text, for example using base64

Choose your preferred function to convert from ArrayBuffer to string from Converting between strings and ArrayBuffers

var  publicKeyB64 = btoa(ab2str(keydata));
document.getElementById("key").innerHTML = publicKeyB64;
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Hi thanks for the input. I tried a variety of the functions listed on the page, but often got an error about the chars being outside of the latin1 range, removing the base-64 btoa they worked, but outputted Asian chars. I managed to get the above working under EDIT, but was wondering if the 'keydata' only contains the public key? or is there extra information which is being output, as the output contains more characters then i expected for a public key. Hope this makes sense, thanks. – Future Jun 23 '18 at 15:26
  • 1
    `keydata` only contains the public key. Base64 uses A-Z, a-z, 0-9, +,/ characters. Maybe the last two are giving you problems when you set the innerHTML. I suggest you use an input text. – pedrofb Jun 23 '18 at 16:07