veraison / go-cose

go library for CBOR Object Signing and Encryption (COSE)
Mozilla Public License 2.0
50 stars 26 forks source link

Consider Interface simplicity and safer usage of Sign1 #68

Closed yogeshbdeshpande closed 2 years ago

yogeshbdeshpande commented 2 years ago

This issue is an extension of Issue #64. Issue #64 modified the external Interface for API Sign1 to return Encoded CBOR signed Sign1 message.

However the mis-use is still possible via the Interface API Method: 'func (m *Sign1Message) Sign() '

Example: Step 1: User Instantiates (m *Sign1Message) Message

Step 2: User sets all the elements of the structure(like payload, protected headers etc.)

Step 3: User calls m.Sign()

Step 4: User gets the signature set in the m field due to this API invocation.

Step 5: User then modifies m.Signature field ?

One possible solution to this problem is to make the API Method Sign() as local function sign() and let the users only provide: Generic API Function:

func Sign1(rand io.Reader, signer Signer, protected ProtectedHeader, payload, external []byte) (cbor_msg []byte, err error)

The benefit is that User is un-aware of the Cose_Sign1 Message, but just supplies the needed inputs. Also, it is less prone to errors on the user side.

The obvious drawback, the interface is simple (not richer), which may be needed for some applications?

In my view the benefits outweigh the disadvantages, so should be adapted however, a careful impact analysis on dependencies/users of go-cose Veraison library needs to be evaluated.

shizhMSFT commented 2 years ago

The useability drawback of sole Sign1() function is that it is not possible to modify the unprotected headers after signing. Scenarios like counter signatures and timestamps are not achievable with Sign1() only.

Here's an example flow:

  1. User Instantiates m *Sign1Message Message
  2. User sets all the elements of the structure (like payload, protected headers etc.)
  3. User calls m.Sign()
  4. User gets the Signature set in the m field due to this API invocation.
  5. User constructs a timestamping request based on m.Signature.
  6. User sends the timestamping request and obtains a timestamping signature.
  7. User adds the timestamping signature to m.Headers.Unprotected.
  8. User encodes m.
SteveLasker commented 2 years ago

Moving to a documentation issue.