in-toto/in-toto-golang

Verification using ED25519 keys for functionaries returns error

anotherbridge opened this issue · 9 comments

General information:

I am using a similar setup as described in #207.
In the demo project I replaced the keys of bob and carl by ED25519 versions in PEM format. I created the keys in the root.layout using the command in-toto key layout bob/carl.

  • Version (tag or commit): checked out repo at state of commit 3dcfea3
  • Operating system (Linux/Mac/Windows): Debian 11.6 x86 architecture
  • Go version: go version go1.20.1
  • Go build flags (if any):

Description of the bug:

Running all the steps in demo-project works without an issue unless I want to verify the result. When running the verification I get the following:

in-toto verify --layout root.layout --layout-keys alice.pub

inspection failed: invalid signature: crypto/rsa: verification error

Yet when creating everything up until the verification step using the Golang verison of in-toto and then at the verification step I use the python version instead the verification is successful. The command I ran in the end is:

in-toto-verify --layout root.layout --layout-key alice.pub

The exit code is zero as it would be expected.

Due to the error message I am assuming that instead of using ED25519 for the verification of the corresponding signatures, RSA is used.

Hi @anotherbridge, could you share the layout you generated?

Hi @adityasaky, of course,

here is the layout:
root.layout.txt

And additionally, these are the public keys:
bob.pub.txt
carl.pub.txt

Can you also share the link metadata? Thanks!

Here's the complete final_product directory before running the verification step:
final_product.tar.gz

Hi @anotherbridge, sorry for the delay. The issue is the same as this: in-toto/in-toto#186 (comment). We should, IMO, get rid of private altogether from serialized metadata in this implementation. In summary, in-toto-golang, when canonicalizing the layout to verify the signature, includes an empty private string for each key in keyval. The layout created by the python implementation omits this. I can verify it works with the following layout which I re-signed using Alice's key from the demo:

{
 "signatures": [
  {
   "keyid": "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b588f3e9cc48b35",
   "sig": "5de25885b32fabc042779d0113cece8a88174af45d809d64aea38c3d0a0f92d12264530d8a04d41529bd3c1bce9627fad57f05dbc39acfaeb231f563444a476ea88a5dc484cfd13167305ff32d6a9ae12e4f1c8d1d1539929bfb1d5efa3e6c95c5842621c7b06381450f83887e20abb4032e082fde33f8c9100656d90d9e5ee9c78bbda8deba53c3daaf461deca7d3c7437ef5b413a055813160801cbc25f54cb794e25c4d6a382f8b0afa51ec065237cbc1815c4ddfd41b404dec0c8480e7c14dc69a3c31ba81e3a7030432bcabce51114be71c1ab683e18667b2b4793c04cfd3f965c6d1b22c4053a8b1aaa77cd7675d42e96b853f3fc204201d45176e68a85334f42c52ddb61411dc3565b7b2b08eb80117da2638cb4595e5cb7cf04493712774035335c9db34632ed033bc72ca4a081baa937c40c15ad313b5927be446a54eaeb601c61aba86fe55b76cade6db89bb5d4be9d0ab959ec9f71929039b0f6559e3eeda536f7b9043f1ed636226dab9ef9b4d19234725ee7d16fb11c6c4c4c5"
  }
 ],
 "signed": {
  "_type": "layout",
  "expires": "2023-03-23T10:30:24Z",
  "inspect": [
   {
    "_type": "inspection",
    "expected_materials": [
     [
      "MATCH",
      "demo-project.tar.gz",
      "WITH",
      "PRODUCTS",
      "FROM",
      "package"
     ],
     [
      "ALLOW",
      ".keep"
     ],
     [
      "ALLOW",
      "alice.pub"
     ],
     [
      "ALLOW",
      "root.layout"
     ],
     [
      "ALLOW",
      "*.link"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "expected_products": [
     [
      "MATCH",
      "demo-project/foo.py",
      "WITH",
      "PRODUCTS",
      "FROM",
      "update-version"
     ],
     [
      "ALLOW",
      "demo-project/.git/*"
     ],
     [
      "ALLOW",
      "demo-project.tar.gz"
     ],
     [
      "ALLOW",
      ".keep"
     ],
     [
      "ALLOW",
      "alice.pub"
     ],
     [
      "ALLOW",
      "root.layout"
     ],
     [
      "ALLOW",
      "*.link"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "name": "untar",
    "run": [
     "tar",
     "xzf",
     "demo-project.tar.gz"
    ]
   }
  ],
  "keys": {
   "2a304ef310d749d20daa25a5de8439fd4fa2a7abadfdb85ea61d6baa750c0562": {
    "keyid": "2a304ef310d749d20daa25a5de8439fd4fa2a7abadfdb85ea61d6baa750c0562",
    "keyid_hash_algorithms": [
     "sha256",
     "sha512"
    ],
    "keytype": "ed25519",
    "keyval": {
     "private": "",
     "public": "9d608e405d8957d8b3a3c10e1b5c140464bda00b22c48b09b39fb1d159058a40"
    },
    "scheme": "ed25519"
   },
   "36a4147f326b50061d7f3c39355a82af9415e5e75d8dff18d745be40a2933092": {
    "keyid": "36a4147f326b50061d7f3c39355a82af9415e5e75d8dff18d745be40a2933092",
    "keyid_hash_algorithms": [
     "sha256",
     "sha512"
    ],
    "keytype": "ed25519",
    "keyval": {
     "private": "",
     "public": "0fbdf3d86eb3284613def3b2b5a6333ed0f1c3fd8ac34dbccbb5ddfe73f75c88"
    },
    "scheme": "ed25519"
   }
  },
  "readme": "",
  "steps": [
   {
    "_type": "step",
    "expected_command": [
     "git",
     "clone",
     "https://github.com/in-toto/demo-project.git"
    ],
    "expected_materials": [],
    "expected_products": [
     [
      "CREATE",
      "demo-project/foo.py"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "name": "clone",
    "pubkeys": [
     "36a4147f326b50061d7f3c39355a82af9415e5e75d8dff18d745be40a2933092"
    ],
    "threshold": 1
   },
   {
    "_type": "step",
    "expected_command": [],
    "expected_materials": [
     [
      "MATCH",
      "demo-project/*",
      "WITH",
      "PRODUCTS",
      "FROM",
      "clone"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "expected_products": [
     [
      "MODIFY",
      "demo-project/foo.py"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "name": "update-version",
    "pubkeys": [
     "36a4147f326b50061d7f3c39355a82af9415e5e75d8dff18d745be40a2933092"
    ],
    "threshold": 1
   },
   {
    "_type": "step",
    "expected_command": [
     "tar",
     "--exclude",
     ".git",
     "-zcvf",
     "demo-project.tar.gz",
     "demo-project"
    ],
    "expected_materials": [
     [
      "MATCH",
      "demo-project/*",
      "WITH",
      "PRODUCTS",
      "FROM",
      "update-version"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "expected_products": [
     [
      "CREATE",
      "demo-project.tar.gz"
     ],
     [
      "DISALLOW",
      "*"
     ]
    ],
    "name": "package",
    "pubkeys": [
     "2a304ef310d749d20daa25a5de8439fd4fa2a7abadfdb85ea61d6baa750c0562"
    ],
    "threshold": 1
   }
  ]
 }
}

We could likely update https://github.com/in-toto/in-toto-golang/blob/master/in_toto/model.go#L34 to make the Private field private (pun intended) and add interfaces to populate it when loading a key to sign something. Do you think you could explore this? 😄

@adityasaky Sorry for the long delay. First of all I can confirm that adding a private field with an empty string resolves the problem. Second, I am personally not yet experienced with Golang, thus at the moment I am not able to sufficiently explore the suggested change. Yet, I would be pleased to test any updates that have been made regarding this problem.

#222 (comment)

Picking this up with #224. I can confirm that the root.layout.txt signature from this PR can be verified. I didn't run the full in-toto verify workflow because I don't have all the metadata anymore. But, the missing private field is not added in by in-toto-golang anymore as far as I can tell.

@anotherbridge I'm going to close this issue for now as the omitempty seems to ensure it's not part of the canonicalized json representation. Feel free to add info / reopen if I've missed something!