cli icon indicating copy to clipboard operation
cli copied to clipboard

Add support for cosign encrypted private keys

Open mafrosis opened this issue 4 years ago • 4 comments

I have a private key made by cosign which errors during inspect, specifically in the call to asn1.Unmarshall.

With the minimal example it should be easy to recreate the issue - frankly I'm not sure if this is smallstep bug or issue, so please close if appropriate :)

> cosign generate-key-pair
Enter password for private key:
Enter again:
Private key written to cosign.key
Public key written to cosign.pub
> sed -i 's/ENCRYPTED COSIGN PRIVATE KEY/ENCRYPTED PRIVATE KEY/g' cosign.key
> step crypto key inspect cosign.key
Please enter the password to decrypt cosign.key:
error decrypting cosign.key: failed to unmarshal private key: asn1: structure error: tags don't match (16 vs {class:1 tag:27 length:34 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} encryptedPrivateKeyInfo @2

As mentioned on gitter, the data "payload" of the private key from cosign looks like following, whereas keys created by step crypto keypair appear to have a binary "payload". Following is from debug print statements in pkcs8.go:

{
  "kdf": {
    "name": "scrypt",
    "params": {
      "N": 32768,
      "r": 8,
      "p": 1
    },
    "salt": "r2LB ..snip.. AQcc="
  },
  "cipher": {
    "name": "nacl/secretbox",
    "nonce": "nYWq ..snip.. UkhYE"
  },
  "ciphertext": "RXCC ..snip.. hTpA=="
}

mafrosis avatar May 20 '21 21:05 mafrosis

I've been looking at this, and the problem is that cosign does not use the PKCS#8 encryption defined in RFC7468. They use encryption based on NaCl SecretBox using a secret derived from the given password using scrypt.

The implementation is in the encrypted package of https://github.com/theupdateframework/go-tuf, and I can't find the definition of the encryption in the TUF spec

maraino avatar May 21 '21 22:05 maraino

Assuming you are on the Sigstore Slack, there is some useful info here in a thread.

To quote from Dan Lorenc on that thread:

There are many ways to store the keys on disk Cosign keys are encrypted using nacl secret box But otherwise they're just plain ecdsa keys So cosign first decrypts that (after checking the header) Then even after that step there are many ways of representing an ec keypair, we assume they're in the asn.1 format

So if I understand this right, I can use the commands in https://smallstep.com/docs/step-cli/reference/crypto/nacl/secretbox to work with cosign keys

mafrosis avatar Jun 02 '21 02:06 mafrosis

@mafrosis yes, and not. To use step crypto nacl secretbox, you first will need to derive the secretbox key from the password using scrypt. Step supports scrypt, but as it doesn't allow you to set the salt, so you cannot derive the proper key just using step.

In any case, we will add support to these keys in go.step.sm/crypto.

maraino avatar Jun 02 '21 03:06 maraino

@mafrosis just hacked this to add support in the cli https://github.com/smallstep/crypto/pull/20

maraino avatar Sep 11 '21 04:09 maraino