ipfs / specs

Technical specifications for the IPFS protocol stack
https://specs.ipfs.tech
1.16k stars 231 forks source link

need for clarification on how a Record is really structured #24

Closed daviddias closed 9 months ago

daviddias commented 9 years ago

The type Record appears several times through the spec with different formats

type Record struct {
  Value     []byte
  Expires   time.Duration
  Signature []byte
}
Record Node {
  Scheme   Link // link to a validity scheme
  Value    Link // link to an object representing the value.
  Version  Data // record version number
  Validity Data // data needed to satisfy the validity scheme
}
type Record struct {
  Scheme    Link // link to the validity scheme
  Signature Link // link to a cryptographic signature over the rest of record
  Value     Data // an opaque value
}
type Record struct {
  Scheme    Link // link to the validity scheme
  Signature  Link // link to a cryptographic signature over the record
  Expires   Data // datetime at which record expires
  Value     Data // an opaque value
}

Shouldn't it be just the last one?

jbenet commented 9 years ago

No, the point is that records depend on your type. not all records need sigs. not all records need expired. not all ...

jbenet commented 9 years ago

https://github.com/ipfs/specs/tree/master/records#example-record-types

whyrusleeping commented 9 years ago

image

jbenet commented 9 years ago

@diasdavid i want to do signatures uniformly, like this:

type Signature struct {
  PublicKey dag.Link 
  Object dag.Link
  Bytes []byte  // sign(privateKey, Object.Hash) 
}

that way signatures can be uniform. see the "keychain" WIP: https://github.com/ipfs/specs/tree/master/keychain

daviddias commented 9 years ago

Following thread on IRC, this still seems weird:

type Record struct {
  Scheme    Link // link to the validity scheme
  Signature Link // link to a cryptographic signature over the record
  Expires   Data // datetime at which record expires
  Value     Data // an opaque value
}

shouldn't it be

type Signature struct {
  Key       Link // the key used to sign
  Algorithm Link // the algorithm used to sign the signee
  Encoding  Link // the encoding the sig is serialized with
  Signee    Link // the object the key is signing (in this case the Record)
  Bytes     Data // the raw signature bytes
}

and then

type Record struct {
  Scheme    Link // link to the validity scheme
  Expires   Data // datetime at which record expires
  Value     Data // an opaque value
}
jbenet commented 9 years ago

@diasdavid you're totally right!

daviddias commented 9 years ago

Found out that using ECDSA opens a side-channel attack if the ECDH key pair is used considerably, if the curve secp256k1 is picked, ref: http://eprint.iacr.org/2014/161.pdf

A possible solution would be to use a different curve that doesn't have this vulnerability, however, the recommended way to mitigate this is by avoiding using the same key several times, creating a new key for each sig. Also ensuring freshness of keypair might be a good thing (and it follows the pattern observed in Notary)

This requires IPRS to change to something like:

type RecordSignature struct {
  KeySignature       Link // the signature of the pubkey used to sign this Record
  Algorithm Link // the algorithm used to sign the signee
  Encoding  Link // the encoding the sig is serialized with
  Signee    Link // the object the key is signing (in this case the Record)
  Bytes     Data // the raw signature bytes
}

type PubKeySignature struct {
  Key      Link // the pubkey used to sign (or in another words, the PubKey that refers to the 'root' PrivKey
  Algorithm Link // the algorithm used to sign the signee
  Encoding  Link // the encoding the sig is serialized with
  Signee    Link // the object the key is signing (in this case the the PubKey that was used to sign the Record) 
  Bytes     Data // the raw signature bytes
}

// Key represents a cryptographic key
type Key struct {
  Algorithm Link // the algorithm used to generate the key
  Encoding  Link // the encoding used to store the key
  Bytes     Data // the raw key bytes
}

type Record struct {
  Scheme    Link // link to the validity scheme
  Expires   Data // datetime at which record expires
  Value     Data // an opaque value
}

Please double check this to make sure I'm not missing anything or not adding complexity without any need

jbenet commented 9 years ago
type RecordSignature struct {
  Key       Link // the key used to sign this Record
  Algorithm Link // the algorithm used to sign the signee
  Encoding  Link // the encoding the sig is serialized with
  Signee    Link // the object the key is signing (in this case the Record)
  Bytes     Data // the raw signature bytes
}

type Key struct {
   ... // from keychain
}

type SignedKey struct {
  Key       Link // the key that is signed
  ParentKey Link // the key that signed this key
  Identity  Link // the identity this key represents (should be derived from ParentKey)
  Signature Link // the Signature on Key, by priv key corresponding to ParentKey
}
jbenet commented 9 years ago

another stab at SignedKey

type SignedKey struct {
  Signature Link // the Signature on Key, by priv key corresponding to ParentKey
}

// the key that is signed
func (k *SignedKey) Key() Key {
  return k.Signature.Object
}

// the key that signed this key
func (k *SignedKey) ParentKey() Key {
  return k.Signature.Key
}

// the identity this key represents (derived from ParentKey)
func (k *SignedKey) Identity() Key {
  return k.Signature.Key.Identity()
}
daviddias commented 9 years ago
type Signature struct {
  Key       Link // the signature of the pubkey used to sign this Record
  Algorithm Link // the algorithm used to sign the signee
  Encoding  Link // the encoding the sig is serialized with
  Signee    Link // the object the key is signing (in this case the Record)
  Bytes     Data // the raw signature bytes
}

type SignedKey struct {
    Signature Link // the Signature on Key, by priv key corresponding to ParentKey
}

// Key represents a cryptographic key
type Key struct {
  Algorithm Link // the algorithm used to generate the key
  Encoding  Link // the encoding used to store the key
  Bytes     Data // the raw key bytes
}

type Record struct {
  Scheme    Link // link to the validity scheme
  Expires   Data // datetime at which record expires
  Value     Data // an opaque value
}
whyrusleeping commented 9 years ago

If a key can be broken by simply using it a few times, I dont think that a type of key I would really want to be using...

ghost commented 9 years ago

http://safecurves.cr.yp.to/

ianopolous commented 9 years ago

I would avoid secp256k1. Use ed25519 as in tweetnacl. As far as I can see, there is very little reason to use any other public key crypto these days, with the exception of post quantum algorithms, or if you need legacy support.

jbenet commented 9 years ago

RSA is not broken either and some credible cryptographers suspect may outlast ed25519 (though I personally suspect otherwise). Though djb is one of our saints, he's not the only one. In any case, we should not proscribe against using any keys we so far THINK are safe, we should avoid using those we KNOW are not safe (including significantly weakened but not fully broken algorithms).

(TL;DR: multikey with all the safe things. And yeah we should not use secp256k1)

— Sent from Mailbox

On Mon, Sep 21, 2015 at 1:12 PM, Ian Preston notifications@github.com wrote:

I would avoid secp256k1. Use ed25519 as in tweetnacl. As far as I can see, there is very little reason to use any other public key crypto these days, with the exception of post quantum algorithms, or if you need legacy support.

Reply to this email directly or view it on GitHub: https://github.com/ipfs/specs/issues/24#issuecomment-142095817

ianopolous commented 9 years ago

RSA isn't broken, but I still wouldn't pick it for a new system (obviously it can be an option in a multikey, but for example I wouldn't default to it in IPNS). The main negatives of RSA are: 1) large key size (4-16X larger than 25519) 2) the large random prime hunt required to generate keys (25519 can just take a random byte array) 3) complexity of implementation, and thus likelihood of bugs in implementation. (the entire tweetnacl library is 900 lines of C, including boxing, signing, secret boxing and hashes)