Generating signed messages using CMS and PKI.js

One of the most common signature formats on the web is known as CMS SignedData, this is the signature format used in PDF files, CAdES, S/MIME and several other digital signature solutions.

As a signature it has a few notable features:

  1. Having multiple signers.
  2. Including meta-data that will be signed along with the data that is being signed.
  3. Including meta-data that is outside the scope of the signature.
  4. Signing data contained within the signature or data referenced by it.

These traits mean you can do some interesting things like implementing counter-signing in-turn enabling notarization scenarios.

Utilizing PKI.js you can now create and verify this signature format, bellow is an example of how creating one of these messages looks using this library:

// #region Put a static values 
var sample_data = new Uint8Array(sample_data);
sample_data[0] = 0x00;
sample_data[1] = 0x01;
sample_data[2] = 0x02;
sample_data[3] = 0x03;
sample_data[4] = 0x04;

cms_signed_simpl = new org.pkijs.simpl.CMS_SIGNED_DATA({
    digestAlgorithms: [
        new org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.3.14.3.2.26" }) // SHA-1
    ],
    encapContentInfo: new org.pkijs.simpl.cms.EncapsulatedContentInfo({
        eContentType: "1.2.840.113549.1.7.1", // "data" content type
        eContent: new org.pkijs.asn1.OCTETSTRING({ value_hex: sample_data })
    }),
    signerInfos: [
        new org.pkijs.simpl.CMS_SIGNER_INFO({
            sid: new org.pkijs.simpl.cms.IssuerAndSerialNumber({
                issuer: cert_simpl.issuer,
                serialNumber: cert_simpl.serialNumber
            }),
            digestAlgorithm: new org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.3.14.3.2.26" }), // SHA-1
            signatureAlgorithm: new org.pkijs.simpl.ALGORITHM_IDENTIFIER({ algorithm_id: "1.2.840.113549.1.1.5" }), // RSA + SHA-1
        })
    ],
    certificates: [cert_simpl]
});
// #endregion 

return cms_signed_simpl.sign(privateKey, 0);

In this sample you can see we are putting our content to be signed within the SignedData message and then signing it with RSA and SHA1, this is in-the exact same thing that is needed to implement what is called opaque signed email in S/MIME.

 

Frankencerts, new extensions and PKI.js

One of the things that we wanted you to be able to use the PKI.js libraries for is the X.509 Certificates, including those with new extensions (like testing for OCSP MUST Staple or for testing other certificate processing libraries like was done in the Frankencert paper.

Here is an example of what that might look like:

function create_cert()
{
    // #region Initial variables 
    var sequence = Promise.resolve();

    var cert_simpl = new org.pkijs.simpl.CERT();

    var publicKey;
    var privateKey;
    // #endregion 

    // #region Get a "crypto" extension 
    var crypto = org.pkijs.getCrypto();
    if(typeof crypto == "undefined")
    {
        alert("No WebCrypto extension found");

        return;
    }
    // #endregion 

    // #region Put a static values 
    cert_simpl.serialNumber = new org.pkijs.asn1.INTEGER({ value: 1 });
    cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({
        type: "2.222.333",
        value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" })
    }));
    cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({
        type: "2.222.444",
        value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" })
    }));
    cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({
        type: "2.222.333",
        value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" })
    }));
    cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({
        type: "2.222.444",
        value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" })
    }));
    cert_simpl.notBefore.value = new Date();
    cert_simpl.notAfter.value = new Date(2016, 01, 01);

    cert_simpl.extensions = new Array(); // Extensions are not a part of certificate by default, it's an optional array

    // #region "BasicConstraints" extension
    var basic_constr = new org.pkijs.simpl.x509.BasicConstraints({
        cA: true,
        pathLenConstraint: 3
    });

    cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({
        extnID: "2.5.29.19",
        critical: false,
        extnValue: basic_constr.toSchema().toBER(false),
        parsedValue: basic_constr // Parsed value for well-known extensions
    }));
    // #endregion 

    // #region "KeyUsage" extension 
    var bit_array = new ArrayBuffer(1);
    var bit_view = new Uint8Array(bit_array);

    bit_view[0] = bit_view[0] | 0x02; // Key usage "cRLSign" flag
    bit_view[0] = bit_view[0] | 0x04; // Key usage "keyCertSign" flag

    var key_usage = new org.pkijs.asn1.BITSTRING({ value_hex: bit_array });

    cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({
        extnID: "2.5.29.15",
        critical: false,
        extnValue: key_usage.toBER(false),
        parsedValue: key_usage // Parsed value for well-known extensions
    }));
    // #endregion 

    cert_simpl.signatureAlgorithm.algorithm_id = "1.2.840.113549.1.1.5"; // RSA + SHA-1
    cert_simpl.signature.algorithm_id = cert_simpl.signatureAlgorithm.algorithm_id; // Must be the same value
    // #endregion 

    // #region Create a new key pair 
    sequence = sequence.then(
        function()
        {
            return crypto.generateKey({ name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: { name: "sha-1" } }, true, ["encrypt", "decrypt", "sign", "verify"]);
        }
    );
    // #endregion 

    // #region Store new key in an interim variables
    sequence = sequence.then(
        function(keyPair)
        {
            publicKey = keyPair.publicKey;
            privateKey = keyPair.privateKey;
        },
        function(error)
        {
            alert("Error during key generation: " + error);
        }
    );
    // #endregion 

    // #region Exporting public key into "subjectPublicKeyInfo"  
    sequence = sequence.then(
        function()
        {
            return cert_simpl.subjectPublicKeyInfo.importKey(publicKey);
         }
    );
    // #endregion 

    // #region Signing final certificate 
    sequence = sequence.then(
       function()
       {
           return cert_simpl.sign(privateKey);
       },
       function(error)
       {
           alert("Error during exporting public key: " + error);
       }
    );
    // #endregion 

    sequence = sequence.then(
        function()
        {
            alert("Good result");
        },
        function(error)
        {
            alert("Error during signing: " + error);
        }
    );

    sequence.then(
        function()
        {
            return cert_simpl.verify();
        }
    ).then(
        function(result)
        {
            alert("Verification passed: " + result);
        },
        function(error)
        {
           alert("Verification failed: " + eror);
        }
    );
}

As you can see the library is designed in such a way you are not limited to the creation of some static pre-conceived layouts of these structures, you can fairly easily construct any type of certificate (or any of the other supported message types).

At a later date (if it makes sense to do so) we may also decide to add a simple layer ontop of this that abstracts out the need to understand encoding concepts as well.

This layered approach ensures the library can be used to create real-applications without the need to hack up the underlying APIs enabling developers to avoid the need to understand low-level  ASN.1 formats in detail.

Potential projects for PKI.JS

This is a list of potential projects that would benefit from PKI.js, can you think of any others that would be interesting?

  1. Adding signing, time-stamping and verifying support to pdf.js.
  2. Creating a smime.js on email.js that provides signing, verifying, encryption, decryption of S/MIME.
  3. Creating a CAdES library for web pages.
  4. Adding signature support to web document management solutions.
  5. Adding encrypted mail support in webmail offerings.
  6. Building a usable and modern certificate based authentication solution using web markup for credential selection.
  7. Creating a rich user experience for the short-lived certificates providing temporary access via SSH and TLS.

With some changes the libraries could be used in server side projects:

  1. Creating an OCSP responder based on node.js.
  2. Creating a simple CA on node.js

WebCrypto and PKI

Like it or not here it comes — within the next few months WebCrypto will be supported in various degrees across all mainstream browsers. There are plenty of posts out there talking about the security concerns of performing cryptography in the browser so I wont go into those here.

What I wanted to talk about was now that it’s here (mostly) what can we do with it? There will be those who say you do harm by making any claims about the assurances a web application makes relating to identity and confidentiality when WebCrypto is involved. The reality though is its happening and we should think about how we enable applications to use it responsibly.

This is why I started work on PKI.JS and ASN1.JS with Yuri Strozhevsky. Now that browsers have these basic crypto primitives available to them it is possible to build web applications that are interoperable with the security services used off the web, it is also possible to build new services on the web that simply were not possible before.

Now there have been libraries that that offered ASN.1 and PKI related capabilities (for example jsRSAsign, Forge and Lapo-asn1js) but none of these were complete and none built around WebCrypto as the source of crypto.

What Yuri and I set out to do is create a set of libraries that addressed these gaps and used public test suites (when available) to ensure conformance with the associated standards, including:

  1. X.509 and CRLs– RFC 5280
  2. CMS / PKCS 7 (Signed & EnvelopedData) – RFC 5652
  3. PKCS10 – RFC 2986
  4. PKCS8 – RFC 5208
  5. OCSP – RFC 6960
  6. Time-stamping – RFC 3161

For example for ASN.1 Yuri used his freely available test suite and for path building he tested against the PKITS test suite.

This of course does not mean the libraries are 100% compliant or defect free, in-fact I can promise you they are not but where test suites were clearly available we tried to utilize them so we would end up with a highly stable and standards compliant library.

At this point the libraries work in all modern browsers but only support signing, verifying, encrypting and decrypting in the Chrome dev-channel but in theory should work on Firefox nightlies as well. Unfortunately the profile and version of WebCrypto supported by Internet Explorer is outdated enough at this point these features do not work there at all yet.

These libraries have not yet been published to their public repositories but I expect them to be within the week under an BSD style license, to give some perspective on the size of this project I expect it to be just under 20,000 lines of code when released. It’s my hope that other people take this and build upon them so that the Internet has a browser friendly way to interact with these technologies.

NOTE: While I hate disclaimers like this but these libraries have not undergone any significant review please do not consider them production ready more work is needed before that’s the case.

NOTE: It’s also worth noting that until at least two browsers release their WebCrypto implementations as final products that these libraries may stop working or not work uniformly across browsers, for example at this time the nightly Chrome builds do nor support key exports which prevents implementation of the key storage structures.

P.S I actually miss spoke earlier, we did not end up include PKCS #12 in this version but most of the base structures are supported.

The bias of experience and ignorance of youth

It was really security (well pirate and BBS’s and IRC channels) that first got me seriously into computers. It was a place where I was surrounded with brilliant people and super interesting problems to explore. It did not take long for me to discover cryptography. I remember the first time I encountered the concepts; I was working on cracking a game and the publisher actually had encrypted some of the instructions and I had to figure out what it was they had used, how it worked and how to work around it.

At that moment I was hooked. Since then nearly every professional experience I have had has been in computer security — simply put I love this stuff.

As it turns out most of the last two decades I have ended up working on authentication systems of one sort of another; these end up being interesting applications of protocol design, performance design patterns and cryptography.

The nature of these spaces also resulted in me working on operating systems and security services which in turn led me to have a strong bias against the “web developers” who I viewed largely as script kiddies with no understanding of computer science fundamentals let alone security. So much so I discouraged my son from learning many of the associated technologies because “real programmers” don’t bother with such things.

There has been an amazing shift over the last decade and even if at one point I was right for the above position I certainly would not be today. Not only have the technologies that are used to make up the web evolved to the point that they are as impressive and powerful as many of their native counterparts but many of the engineers working with them have become world-class as well.

This has led to some interesting trends the most poignant being the adoption of Javascript as a language for use outside of the browser like in Node.JS and the Tessel. This has been enabled by a competitive race to build the fastest experience on the web, which has become totally dependent on Javascript.

As a technologist I love this as it makes technology more approachable, it makes it easier for things to be rapidly be built and creates portability of skill across the layers of an engineering project.

As a security practitioner it gives me pause; those of you who know me one of my favorite sayings is “Just because you can, doesn’t mean you should” and since this approachability and increased speed of innovation has obvious and natural negative implications when securing systems I am hesitant still to embrace it fully.

I take solace in this dichotomy because of something my mom would always tell me – You’re not learning if your not falling.

As we look at the features in HTML 5 and their support of things like WebCrypto, WebSockets and (god forbid) WebGL I try to remind myself how important it is not to let our personal biases hold back innovation while holding onto the rational and caution approach of my inner security practitioner.

Bitcoin Paper Wallets and Digital Backups

The folks working on Armory have done a wonderful job thinking about many of the risks associated with Bitcoin and Paper Wallets. The have even gone as far to consider the risks of a compromised printer with a feature they call SecurePrint™.

In the Certificate Authority world when managing secrets that can not be kept within a Hardware Security Module (HSM) we go a further by using similar key management tools on Tempest hardware physically located in Faraday cage under rigorous ceremonies designed to ensure every single step performed is confidential, verified and audited.

For the individual moderate Bitcoin holdings Armory provides a robust story for managing wallet keys and producing paper wallets especially when paired with something like the PiWallet. That said since once doesn’t need to physically take your Bitcoin (they can just take a copy of it) make it their own how you store it is also important.

For valuable secrets that must be stored on paper a Certificate Authority would fold the corresponding paper in half taping each of the open ends close using tamper evident seals.

They would then place each sealed paper into their own opaque tamper evident bags keeping inventory of the bag and seal serial numbers, who was present and then storing the bags and inventory in separate secure locations.

This not only makes it possible to detect what has happened with the stored paper but protects it from water as well. Consideration is also given to what kind of paper and toner is used; for most scenarios one would use archival quality paper and high quality toner. But paper burns and toners are made of organics that can break down in heat so electronic copies are often also kept.

When it comes to those electronic records the choice of what media you use to store those values is important, as many types of media are not reliable for long-term storage. Today I would use the MDISC which effectively engraves the data into a disc that is still readable by modern DVD and BluRay players promising the disc to be readable for 1,000 years.

Even though most data being stored would already be cipher-text one never wants to rely on a single point of failure and for this reason another layer of crypto would typically be used. Commonly this is as simple as using GPG or TrueCrypt with a password to encrypt the data you are going to write to the disc in-turn managing the security of that password carefully.

At this point your down to being concerned with the physical protections your storage facilities offer and ensuring you have long term access to the hardware and software necessary to use the artifacts captured above.

Keeping long-term passwords secured

We all know that passwords should be changed regularly to reduce the value to an attacker and that they should be stored in ways that they can not be easily compromised which is why generally people are encouraged not to write passwords down.

The reality is that the human brain can only retain so much information and the less often you use something the more likely it is that you will forget it.

This is true regardless of how memorable your password happens to be.

This is especially true for passwords used in key management ceremonies. Imagine being there when the first keys were generated for the first root CA on the Internet, this is a key that will exist for decades and the implications for loosing access to this key are huge. More over the passwords involved in these ceremonies do not bellong to an individual, they belong to an organization.

For these reasons key management ceremonies use password record forms; I have attached an example form to this post for your reference.

These forms once filled out are stored securely, how securely being dependent on the security needs of the scenario. For example if the password was associated with a share in a Shamir Secret Sharing scheme (M of N set of keys) one would transport and store them securely in facilities geographically distributed under lock and an dual lock control scheme.

Periodically these stored values are retrieved and changed, as part of a process to ensure continued access to systems and keys is possible.

While not something the average person needs to deal with it is relevant to those doing paper key management for large amounts of Bitcoin, important DNSSEC keys or maybe keys embedded into some device that has been mass produced.

Protecting Bitcoin keys with hardware

One of the most important things you can do to keep your Bitcoin keys safe is to get them off of your general-purpose computer and onto a single use device that is designed to perform cryptography or Bitcoin operations.

This protects you from a number of different attacks that could result in the compromise of your keys but it does so at an expense — it makes it more difficult for you to spend your Bitcoin.

This is of course not unique to Bitcoin; in the Certificate Authority world we think of utility keys (e.g. OCSP and Time-stamping) differently than we think of the keys associated with issuing certificate authorities (the ones used to sign subscriber certificates) which we think of differently than keys associated with root certificate authorities. As such we apply different key management techniques and policies to each of them.

The same is true for your bank accounts; you keep less cash in your checking account than you do your savings. This is in part because you have a bankcard and checks tied to the checking account which makes it easier for an attacker to access your funds.

If you manage your Bitcoin holdings in a similar way by having wallets for your “spending money” and wallets for your “savings” then you make it possible to apply security measures that balance convenience and security while managing your risk. These are commonly referred to as “hot” and “cold” wallets.

Additionally those people with large cash assets limit how much they keep in each account so they stay within the liability limits that their financial institutions offer (for example $250,000 USD in the case of FDIC insured institutions).

Traditional banks do the same sort of things; for example a bank with $80,000,000 USD is required to keep $8,000,000 liquid they then use the remainder in fractional reserve banking as a working asset to fund the bank. This also has the side effect of distributing the risk the bank is exposed to by distributing that capital into many different investments each with their own risk profiles.

So how does this all translate to Bitcoin and hardware key management? For most online wallets such as Coinbase are a fine way to manage the funds you spend regularly but for your savings its advantageous to manage these keys yourself instead of being part of a much larger target like an online wallet.

That takes us to Bitcoin key management solutions; Since its introduction there have been many proposed solutions. Most of these being based on either specially hardened and dedicated computers using LiveCDs like this one built on Ubuntu and this one in Tails, these images use wallets like Armory and Electrum to in these clean-room environments to perform Bitcoin operations.

The processes used here are logically equivalent to what Certificate Authorities do with “ceremony computers” where they use specially prepared Tempest rated computers in Faraday Cages with no visibility from the outside that have isolated power (protecting against Differential Power Analysis) to generate and perform operations with sensitive keys.

During these ceremonies ridged processes and controls are used to configure the machines using known software verifying every binary is as its expected to be, auditing every action under camera with multiple people auditing the activities taking place. Also when keys are generated they are protected using secret sharing schemes such as Shamir Secret Sharing and the shares are distributed to different parties who then travel separately and move those shares to secure storage facilities that are geographically distributed.

Obviously there are lots of dials you can “tweak” to control the time / complexity tradeoff involved in the above process but for those with moderate Bitcoin holdings the above would broadly be considered too onerous to even consider.

This is where turnkey products come into play while there have been a number of promising proposals producing something that is secure, usable and affordable is no small task and most of these projects have failed to achieve sufficient market penetration to succeed.

At this time the most promising solutions that are (to varying degrees available) are PiperWallet which is an Open Source printer with embedded RasberryPi that can be used to create paper wallets, based on its claims it has thought about all the right problems (quality of random numbers, etc.)

Another solution is the Open Source PiWallet, this isn’t terribly different than the PiperWallet conceptually (through it does not make any claims about the quality of its random numbers) but it doesn’t include any input or display without an added display and keyboard.

One of the most promising offerings in this space is the Trezor this is a custom designed device designed not only to be useful for cold wallet storage but for actual personal hot wallet use as well. I am looking forward to getting a chance to use one once it becomes generally available.

On the high end of the equation one could also use a Thales nCipher or a SafeNet while these devices are not Bitcoin specific they can be used along with a ceremony computer and a modified Bitcoin wallet to secure the keys used in your wallets.

Above and beyond these solutions there are a half a dozen half-done not maintained smart card solutions (1 ,23) that have potential but unless you’re a JavaCard developer and/or Smart Card Professional these are frankly not viable options yet.

 

Keeping an eye on your Bitcoin keys

In the government, banking and certificate authority worlds important keys are generated and used within specialized cryptographic devices called Hardware Security Modules (HSMs) or their less powerful cousins smart cards.

In the Bitcoin world keys are most commonly generated and stored in software running on the same machines people use for surfing the web. This means those keys are exposed to all of the same risks as the rest of your computing experience.

This is why there are now multiple variants (1, 2, 3) of wallet stealing malware and many cases of Bitcoins being stolen through key compromise (1).

The reality is we have not even touch the tip of the ice-burg on the sorts of attacks that expose these software keys and as Bitcoin becomes more mainstream the techniques used by attackers will improve so that they can overcome the mitigations more advance software is surely to use.

For example a lot of effort was spent mitigating in memory key access threats in Windows by moving keys out of process and working to minimize the amount of time the key was left in its unencrypted form. In-fact the inadequate in-memory protection of keys in OpenSSL was a contributor to the recent #Heartbleed vulnerability.

It is not possible to totally mitigate the risk of in-memory keys but you can reduce the exposure. Even when you do there will still be moments when they or the components that were used to make them may be exposed; For example they may simply get dumped into your page file

So what can you do to protect yourself? The most important mitigation available to you is to do what governments; banks and certificate authorities have been doing for decades – generate and use your keys within specialized devices. The bad news is that even though there are many projects that aspire to help you do just that for Bitcoin your choices are still quite limited – especially if you want ease-of-use and accessibility.

Absent reasonable hardware solutions for key management people often resort to storing their Bitcoins on paper using keys generated on hardened dedicated operating system installs not connected to any network and while this is an useful technique in your arsenal even paper keys can be compromised through carelessness.

In military and aerospace systems things are often designed for triple redundancy and if your storing a large amount of bitcoin you should also keep this principal in mind when designing your key management strategy.

Not doing so sets you up for failure, just look at Mt. Gox. If we believe Mr Karpele’s story he did not know how much Bitcoin he had at any one point and according to reports he also set himself up as a single point of failure.

Though the advent of multi-signature wallets in Bitcoin along with third-party services like BitRated will help people manage this sort of risk in the future it does not mitigate the need for solid accounting and monitoring of your balances.

As such it also makes sense use wallet watcher services such as Blockchain.info’s “Watch Only Addresses” or BTCBalance.net so that you can know what transactions are happening with your keys at any point and time.

If you have a large amount of Bitcoin it also makes sense to use a Honey Pot where you have wallet(s) placed in locations where they are easily accessible and monitored via services like the above so that you know you need to respond accordingly.

In short when thinking about your key management strategy it’s a good idea to keep in mind what Benjamin Franklin said: By failing to prepare, you are preparing to fail.

Insurance and Bitcoin

There are lots of ways we risk loosing our money one of the biggest is when the institutions we trust to keep those funds safe fail to do so.

This happened in the United States during the Great Depression when widespread bank failures destroyed lifetimes of savings overnight.

To address concerns of this happening again the FDIC and NCUA were created in the 1930s to provide assurances that if such an event were to happen again their savings would still be safe and even this has its limits.

This along with regulations that were put into place around minimum liquidity and other practices are what helped people begin to regain trust in the US financial system.

The fall of Mt. Gox and other smaller exchanges has once again introduced similar concerns but thankfully the influx of venture capital to the Bitcoin ecosystem has brought in a new class of organizations who have both the skill and capital to run more professional institutions.

As a result we now are seeing vault services starting to offer similar insurance via self-insurance programs coordinated with underwriters such as Lloyds of London and Meridian.

This is a huge step forward but there is a long way to go before these offerings are viable because as they stand today its far from cost-effective. As an example lets look at Elliptic if we were to store $250,000 USD of Bitcoin (510.58 BTC at todays price) you would be paying $5,064 USD every year for that peace of mind.

That’s not to suggest everyone needs $250,000 of insurance or that this is not a “reasonable” fee for this service but the reality is the price for this assurance has been established and its FREE.

Vaulting services such as Elliptic and Xapo are also a little different than traditional banks because they do not (for the most part) offer other services. Additionally building and operating services that provide the necessary assurances to qualify for such insurance comes at a cost above and beyond the cost of the insurance itself so a premium of some sort must be charged. The costs here are sure to go down as they get amortized across more customers but regardless the current cost structure these services are based on are out of reach of mainstream users.

Making this insurance more accessible will be necessary for us to see this broader adoption of Bitcoin along with many other changes that will include regulations (either self enforced like the NCUA or government mandated). This will include things like reporting requirements, minimum liquidity levels, operational practices, key management requirements and insurance.

When it comes to insurance I think we will also see it become a “freebee” just like in the classical financial institutions where its costs are built into the profit model of the institution. Today classical financial institutions cover these costs via account maintenance fees, transaction fees, the profit they make on the money they hold for others (via fractional reserve banking) and the overall revenue diversity in their business models.

In the meantime the insurance these vaulting services offer fill a market need for those with large amounts of Bitcoin and but not the time or skill to protect the keys themselves.

The irony is of course it’s the little guy who likely needs the insurance more.