github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/naclwrap.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"bytes"
     8  	"crypto/hmac"
     9  	"crypto/rand"
    10  	"crypto/sha256"
    11  	"encoding/base64"
    12  	"fmt"
    13  	"io"
    14  
    15  	"github.com/keybase/client/go/kbcrypto"
    16  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    17  	"github.com/keybase/go-crypto/ed25519"
    18  	"golang.org/x/crypto/nacl/box"
    19  )
    20  
    21  type NaclEncryptionInfo struct {
    22  	Ciphertext     []byte            `codec:"ciphertext"`
    23  	EncryptionType kbcrypto.AlgoType `codec:"enc_type"`
    24  	Nonce          []byte            `codec:"nonce"`
    25  	Receiver       []byte            `codec:"receiver_key"`
    26  	Sender         []byte            `codec:"sender_key"`
    27  }
    28  
    29  const NaclDHKeysize = 32
    30  
    31  // TODO: Ideally, ed25519 would expose how many random bytes it needs.
    32  const NaclSigningKeySecretSize = 32
    33  
    34  // TODO: Ideally, box would expose how many random bytes it needs.
    35  const NaclDHKeySecretSize = 32
    36  
    37  // Todo: Ideally, box would specify nonce size
    38  const NaclDHNonceSize = 24
    39  
    40  const NaclSecretBoxKeySize = 32
    41  
    42  type NaclSigningKeyPair struct {
    43  	Public  kbcrypto.NaclSigningKeyPublic
    44  	Private *kbcrypto.NaclSigningKeyPrivate
    45  }
    46  
    47  var _ GenericKey = NaclSigningKeyPair{}
    48  
    49  type NaclDHKeyPublic [NaclDHKeysize]byte
    50  type NaclDHKeyPrivate [NaclDHKeysize]byte
    51  
    52  type NaclDHKeyPair struct {
    53  	Public  NaclDHKeyPublic
    54  	Private *NaclDHKeyPrivate
    55  }
    56  
    57  func (k NaclDHKeyPair) Clone() (ret NaclDHKeyPair) {
    58  	ret.Public = k.Public
    59  	if k.Private != nil {
    60  		tmp := *k.Private
    61  		ret.Private = &tmp
    62  	}
    63  	return ret
    64  }
    65  
    66  var _ GenericKey = NaclDHKeyPair{}
    67  
    68  type NaclSecretBoxKey [NaclSecretBoxKeySize]byte
    69  
    70  func (k NaclSecretBoxKey) IsZero() bool {
    71  	var z NaclSecretBoxKey
    72  	return hmac.Equal(k[:], z[:])
    73  }
    74  
    75  func importNaclHex(s string, typ byte, bodyLen int) (ret []byte, err error) {
    76  	kid := keybase1.KIDFromString(s)
    77  	return importNaclKid(kid.ToBytes(), typ, bodyLen)
    78  }
    79  
    80  func importNaclKid(bkid []byte, typ byte, bodyLen int) (ret []byte, err error) {
    81  	l := len(bkid)
    82  	if l != bodyLen+3 {
    83  		err = kbcrypto.BadKeyError{Msg: fmt.Sprintf("Wrong length; wanted %d, got %d", bodyLen+3, l)}
    84  		return
    85  	}
    86  
    87  	if bkid[0] != byte(kbcrypto.KeybaseKIDV1) || bkid[l-1] != byte(kbcrypto.IDSuffixKID) || bkid[1] != typ {
    88  		err = kbcrypto.BadKeyError{Msg: "bad header or trailer bytes"}
    89  		return
    90  	}
    91  	ret = bkid[2:(l - 1)]
    92  	return
    93  }
    94  
    95  func BinaryKIDToRawNaCl(k keybase1.BinaryKID) (ret []byte, err error) {
    96  	return importNaclKid([]byte(k), byte(kbcrypto.KIDNaclDH), NaclDHKeysize)
    97  }
    98  
    99  func ImportNaclSigningKeyPairFromBytes(pub []byte, priv []byte) (ret NaclSigningKeyPair, err error) {
   100  	var body []byte
   101  	if body, err = importNaclKid(pub, byte(kbcrypto.KIDNaclEddsa), ed25519.PublicKeySize); err != nil {
   102  		return
   103  	}
   104  	copy(ret.Public[:], body)
   105  	if priv == nil {
   106  	} else if len(priv) != ed25519.PrivateKeySize {
   107  		err = kbcrypto.BadKeyError{Msg: "Secret key was wrong size"}
   108  	} else {
   109  		ret.Private = &kbcrypto.NaclSigningKeyPrivate{}
   110  		copy(ret.Private[:], priv)
   111  	}
   112  	return
   113  }
   114  
   115  func ImportKeypairFromKID(k keybase1.KID) (key GenericKey, err error) {
   116  	kid := k.ToBytes()
   117  	l := len(kid)
   118  	if l < 3 {
   119  		err = kbcrypto.BadKeyError{Msg: "KID was way too short"}
   120  		return
   121  	}
   122  	if kid[0] != byte(kbcrypto.KeybaseKIDV1) || kid[l-1] != byte(kbcrypto.IDSuffixKID) {
   123  		err = kbcrypto.BadKeyError{Msg: "bad header or trailer found"}
   124  		return
   125  	}
   126  	raw := kid[2:(l - 1)]
   127  	switch kid[1] {
   128  	case byte(kbcrypto.KIDNaclEddsa):
   129  		if len(raw) != ed25519.PublicKeySize {
   130  			err = kbcrypto.BadKeyError{Msg: "Bad EdDSA key size"}
   131  		} else {
   132  			tmp := NaclSigningKeyPair{}
   133  			copy(tmp.Public[:], raw)
   134  			key = tmp
   135  		}
   136  	case byte(kbcrypto.KIDNaclDH):
   137  		if len(raw) != NaclDHKeysize {
   138  			err = kbcrypto.BadKeyError{Msg: "Bad DH key size"}
   139  		} else {
   140  			tmp := NaclDHKeyPair{}
   141  			copy(tmp.Public[:], raw)
   142  			key = tmp
   143  		}
   144  	default:
   145  		err = kbcrypto.BadKeyError{Msg: fmt.Sprintf("Bad key prefix: %d", kid[1])}
   146  	}
   147  	return
   148  }
   149  
   150  func ImportDHKeypairFromKID(k keybase1.KID) (*NaclDHKeyPair, error) {
   151  	genericKey, err := ImportKeypairFromKID(k)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	naclKey, ok := genericKey.(NaclDHKeyPair)
   156  	if !ok {
   157  		return nil, fmt.Errorf("expected NaclDHKeyPair, got %T", genericKey)
   158  	}
   159  	return &naclKey, nil
   160  }
   161  
   162  func ImportNaclSigningKeyPairFromHex(s string) (ret NaclSigningKeyPair, err error) {
   163  	var body []byte
   164  	if body, err = importNaclHex(s, byte(kbcrypto.KIDNaclEddsa), ed25519.PublicKeySize); err != nil {
   165  		return
   166  	}
   167  	copy(ret.Public[:], body)
   168  	return
   169  }
   170  
   171  func ImportNaclDHKeyPairFromBytes(pub []byte, priv []byte) (ret NaclDHKeyPair, err error) {
   172  	var body []byte
   173  	if body, err = importNaclKid(pub, byte(kbcrypto.KIDNaclDH), NaclDHKeysize); err != nil {
   174  		return
   175  	}
   176  	copy(ret.Public[:], body)
   177  	if priv == nil {
   178  	} else if len(priv) != NaclDHKeysize {
   179  		err = kbcrypto.BadKeyError{Msg: "Secret key was wrong size"}
   180  	} else {
   181  		ret.Private = &NaclDHKeyPrivate{}
   182  		copy(ret.Private[:], priv)
   183  	}
   184  	return
   185  }
   186  
   187  func ImportNaclDHKeyPairFromHex(s string) (ret NaclDHKeyPair, err error) {
   188  	var body []byte
   189  	if body, err = importNaclHex(s, byte(kbcrypto.KIDNaclDH), NaclDHKeysize); err != nil {
   190  		return
   191  	}
   192  	copy(ret.Public[:], body)
   193  	return
   194  }
   195  
   196  func (k NaclDHKeyPublic) GetKID() keybase1.KID {
   197  	return k.GetBinaryKID().ToKID()
   198  }
   199  
   200  func (k NaclDHKeyPublic) GetBinaryKID() keybase1.BinaryKID {
   201  	prefix := []byte{
   202  		byte(kbcrypto.KeybaseKIDV1),
   203  		byte(kbcrypto.KIDNaclDH),
   204  	}
   205  	suffix := byte(kbcrypto.IDSuffixKID)
   206  	out := prefix
   207  	out = append(out, k[:]...)
   208  	out = append(out, suffix)
   209  	return keybase1.BinaryKID(out)
   210  }
   211  
   212  func (k NaclDHKeyPair) GetFingerprintP() *PGPFingerprint {
   213  	return nil
   214  }
   215  
   216  func (k NaclDHKeyPair) GetAlgoType() kbcrypto.AlgoType {
   217  	return kbcrypto.KIDNaclDH
   218  }
   219  
   220  func (k NaclSigningKeyPair) GetAlgoType() kbcrypto.AlgoType {
   221  	return kbcrypto.KIDNaclEddsa
   222  }
   223  
   224  func (k NaclSigningKeyPair) GetKID() (ret keybase1.KID) {
   225  	return k.Public.GetKID()
   226  }
   227  
   228  func (k NaclSigningKeyPair) GetBinaryKID() (ret keybase1.BinaryKID) {
   229  	return k.Public.GetBinaryKID()
   230  }
   231  
   232  func (k NaclSigningKeyPair) ToShortIDString() string {
   233  	return k.Public.GetKID().ToShortIDString()
   234  }
   235  
   236  func (k NaclDHKeyPair) ToShortIDString() string {
   237  	return k.Public.GetKID().ToShortIDString()
   238  }
   239  
   240  func (k NaclSigningKeyPair) VerboseDescription() string {
   241  	return fmt.Sprintf("255-bit EdDSA signing key (%s)", k.ToShortIDString())
   242  }
   243  func (k NaclDHKeyPair) VerboseDescription() string {
   244  	return fmt.Sprintf("255-bit Curve25519 DH key (%s)", k.ToShortIDString())
   245  }
   246  
   247  func (k NaclSigningKeyPair) GetFingerprintP() *PGPFingerprint {
   248  	return nil
   249  }
   250  
   251  func (k NaclDHKeyPair) GetKID() keybase1.KID {
   252  	return k.Public.GetKID()
   253  }
   254  func (k NaclDHKeyPair) GetBinaryKID() (ret keybase1.BinaryKID) {
   255  	return k.Public.GetBinaryKID()
   256  }
   257  
   258  func (k NaclSigningKeyPair) CheckSecretKey() error {
   259  	if k.Private == nil {
   260  		return NoSecretKeyError{}
   261  	}
   262  	return nil
   263  }
   264  
   265  func (k NaclSigningKeyPair) HasSecretKey() bool {
   266  	return k.Private != nil
   267  }
   268  
   269  func (k NaclSigningKeyPair) Encode() (string, error) {
   270  	return k.GetKID().String(), nil
   271  }
   272  
   273  func (k NaclDHKeyPair) Encode() (string, error) {
   274  	return k.GetKID().String(), nil
   275  }
   276  
   277  func (k NaclDHKeyPair) CheckSecretKey() error {
   278  	if k.Private == nil {
   279  		return NoSecretKeyError{}
   280  	}
   281  	return nil
   282  }
   283  
   284  func (k NaclDHKeyPair) HasSecretKey() bool {
   285  	return k.Private != nil
   286  }
   287  
   288  func (k NaclSigningKeyPair) CanSign() bool { return k.Private != nil }
   289  func (k NaclDHKeyPair) CanSign() bool      { return false }
   290  
   291  func (k NaclSigningKeyPair) Sign(msg []byte) (kbcrypto.NaclSigInfo, error) {
   292  	if k.Private == nil {
   293  		return kbcrypto.NaclSigInfo{}, NoSecretKeyError{}
   294  	}
   295  
   296  	return k.Private.SignInfoV0(msg, k.Public), nil
   297  }
   298  
   299  func (k NaclSigningKeyPair) SecretSymmetricKey(reason EncryptionReason) (NaclSecretBoxKey, error) {
   300  	return NaclSecretBoxKey{}, KeyCannotEncryptError{}
   301  }
   302  
   303  const encryptionReasonMinLength = 8
   304  
   305  type EncryptionReason string
   306  
   307  func (r EncryptionReason) Bytes() []byte {
   308  	return []byte(r)
   309  }
   310  
   311  func (k NaclSigningKeyPair) SignV2(msg []byte, prefix kbcrypto.SignaturePrefix) (kbcrypto.NaclSigInfo, error) {
   312  	if k.Private == nil {
   313  		return kbcrypto.NaclSigInfo{}, NoSecretKeyError{}
   314  	}
   315  
   316  	return k.Private.SignInfoV2(msg, k.Public, prefix)
   317  }
   318  
   319  func (k NaclSigningKeyPair) SignToString(msg []byte) (string, keybase1.SigIDBase, error) {
   320  	return k.Private.SignToStringV0(msg, k.Public)
   321  }
   322  
   323  func (k NaclSigningKeyPair) VerifyStringAndExtract(ctx VerifyContext, sig string) (msg []byte, id keybase1.SigIDBase, err error) {
   324  	var keyInSignature *kbcrypto.NaclSigningKeyPublic
   325  	var fullSigBody []byte
   326  	keyInSignature, msg, fullSigBody, err = kbcrypto.NaclVerifyAndExtract(sig)
   327  	if err != nil {
   328  		return nil, id, err
   329  	}
   330  
   331  	kidInSig := keyInSignature.GetKID()
   332  	kidWanted := k.GetKID()
   333  	if kidWanted.NotEqual(kidInSig) {
   334  		err = WrongKidError{kidInSig, kidWanted}
   335  		return nil, id, err
   336  	}
   337  
   338  	id = kbcrypto.ComputeSigIDFromSigBody(fullSigBody)
   339  	return msg, id, nil
   340  }
   341  
   342  func (k NaclSigningKeyPair) VerifyString(ctx VerifyContext, sig string, msg []byte) (id keybase1.SigIDBase, err error) {
   343  	var keyInSignature *kbcrypto.NaclSigningKeyPublic
   344  	var fullSigBody []byte
   345  	keyInSignature, fullSigBody, err = kbcrypto.NaclVerifyWithPayload(sig, msg)
   346  	if err != nil {
   347  		return id, err
   348  	}
   349  	kidInSig := keyInSignature.GetKID()
   350  	kidWanted := k.GetKID()
   351  	if kidWanted.NotEqual(kidInSig) {
   352  		err = WrongKidError{kidInSig, kidWanted}
   353  		return id, err
   354  	}
   355  
   356  	id = kbcrypto.ComputeSigIDFromSigBody(fullSigBody)
   357  	return id, nil
   358  }
   359  
   360  func (k NaclDHKeyPair) SignToString(msg []byte) (sig string, id keybase1.SigIDBase, err error) {
   361  	err = KeyCannotSignError{}
   362  	return
   363  }
   364  
   365  func (k NaclDHKeyPair) VerifyStringAndExtract(ctx VerifyContext, sig string) (msg []byte, id keybase1.SigIDBase, err error) {
   366  	err = KeyCannotVerifyError{}
   367  	return
   368  }
   369  
   370  func (k NaclDHKeyPair) VerifyString(ctx VerifyContext, sig string, msg []byte) (id keybase1.SigIDBase, err error) {
   371  	err = KeyCannotVerifyError{}
   372  	return
   373  }
   374  
   375  func EncryptionKIDToPublicKeyBytes(bk []byte) ([]byte, error) {
   376  	if len(bk) != 3+NaclDHKeysize {
   377  		return []byte{}, fmt.Errorf("invalid DH encryption key kbcrypto.KID (wrong length)")
   378  	}
   379  	if bk[0] != byte(kbcrypto.KeybaseKIDV1) || bk[1] != byte(kbcrypto.KIDNaclDH) || bk[len(bk)-1] != byte(kbcrypto.IDSuffixKID) {
   380  		return []byte{}, fmt.Errorf("invalid DH encryption key kbcrypto.KID (wrong type)")
   381  	}
   382  	return bk[2 : len(bk)-1], nil
   383  }
   384  
   385  func (k NaclSigningKeyPair) ExportPublicAndPrivate() (RawPublicKey, RawPrivateKey, error) {
   386  	return RawPublicKey(k.GetKID().ToBytes()), RawPrivateKey(k.Private[:]), nil
   387  }
   388  
   389  func (k NaclDHKeyPair) ExportPublicAndPrivate() (RawPublicKey, RawPrivateKey, error) {
   390  	return RawPublicKey(k.GetKID().ToBytes()), RawPrivateKey(k.Private[:]), nil
   391  }
   392  
   393  func makeNaclSigningKeyPair(reader io.Reader) (NaclSigningKeyPair, error) {
   394  	publicKey, privateKey, err := ed25519.GenerateKey(reader)
   395  	if err != nil {
   396  		return NaclSigningKeyPair{}, err
   397  	}
   398  
   399  	var publicArray kbcrypto.NaclSigningKeyPublic
   400  	var privateArray kbcrypto.NaclSigningKeyPrivate
   401  
   402  	copy(publicArray[:], publicKey)
   403  	copy(privateArray[:], privateKey)
   404  
   405  	return NaclSigningKeyPair{
   406  		Public:  publicArray,
   407  		Private: &privateArray,
   408  	}, nil
   409  }
   410  
   411  // MakeNaclSigningKeyPairFromSecret makes a signing key pair given a
   412  // secret. Of course, the security of depends entirely on the
   413  // randomness of the bytes in the secret.
   414  func MakeNaclSigningKeyPairFromSecret(secret [NaclSigningKeySecretSize]byte) (NaclSigningKeyPair, error) {
   415  	r := bytes.NewReader(secret[:])
   416  
   417  	kp, err := makeNaclSigningKeyPair(r)
   418  	if err != nil {
   419  		return NaclSigningKeyPair{}, err
   420  	}
   421  
   422  	if r.Len() > 0 {
   423  		return NaclSigningKeyPair{}, fmt.Errorf("Did not use %d secret byte(s)", r.Len())
   424  	}
   425  
   426  	return kp, err
   427  }
   428  
   429  func MakeNaclSigningKeyPairFromSecretBytes(secret []byte) (NaclSigningKeyPair, error) {
   430  	if len(secret) != NaclSigningKeySecretSize {
   431  		return NaclSigningKeyPair{}, fmt.Errorf("Bad NaCl signing key size: %d", len(secret))
   432  	}
   433  	var fixed [NaclSigningKeySecretSize]byte
   434  	copy(fixed[:], secret)
   435  	return MakeNaclSigningKeyPairFromSecret(fixed)
   436  }
   437  
   438  func GenerateNaclSigningKeyPair() (NaclSigningKeyPair, error) {
   439  	return makeNaclSigningKeyPair(rand.Reader)
   440  }
   441  
   442  func makeNaclDHKeyPair(reader io.Reader) (NaclDHKeyPair, error) {
   443  	pub, priv, err := box.GenerateKey(reader)
   444  	if err != nil {
   445  		return NaclDHKeyPair{}, err
   446  	}
   447  	return NaclDHKeyPair{
   448  		Public:  *pub,
   449  		Private: (*NaclDHKeyPrivate)(priv),
   450  	}, nil
   451  }
   452  
   453  func MakeNaclDHKeyPairFromSecretBytes(secret []byte) (NaclDHKeyPair, error) {
   454  	if len(secret) != NaclDHKeySecretSize {
   455  		return NaclDHKeyPair{}, fmt.Errorf("Bad NaCl DH key size: %d", len(secret))
   456  	}
   457  	var fixed [NaclDHKeySecretSize]byte
   458  	copy(fixed[:], secret)
   459  	return MakeNaclDHKeyPairFromSecret(fixed)
   460  }
   461  
   462  // MakeNaclDHKeyPairFromSecret makes a DH key pair given a secret. Of
   463  // course, the security of depends entirely on the randomness of the
   464  // bytes in the secret.
   465  func MakeNaclDHKeyPairFromSecret(secret [NaclDHKeySecretSize]byte) (NaclDHKeyPair, error) {
   466  	r := bytes.NewReader(secret[:])
   467  
   468  	kp, err := makeNaclDHKeyPair(r)
   469  	if err != nil {
   470  		return NaclDHKeyPair{}, err
   471  	}
   472  
   473  	if r.Len() > 0 {
   474  		return NaclDHKeyPair{}, fmt.Errorf("Did not use %d secret byte(s)", r.Len())
   475  	}
   476  
   477  	return kp, err
   478  }
   479  
   480  func GenerateNaclDHKeyPair() (NaclDHKeyPair, error) {
   481  	return makeNaclDHKeyPair(rand.Reader)
   482  }
   483  
   484  func GenerateNaclSigningKeyPairFromSeed(seed [ed25519.SeedSize]byte) (NaclSigningKeyPair, error) {
   485  	return makeNaclSigningKeyPair(bytes.NewReader(seed[:]))
   486  }
   487  
   488  func KbOpenSig(armored string) ([]byte, error) {
   489  	return base64.StdEncoding.DecodeString(armored)
   490  }
   491  
   492  func SigExtractKbPayloadAndKID(armored string) (payload []byte, kid keybase1.KID, sigID keybase1.SigIDBase, err error) {
   493  	var byt []byte
   494  	var sig kbcrypto.NaclSigInfo
   495  
   496  	if byt, err = KbOpenSig(armored); err != nil {
   497  		return nil, kid, sigID, err
   498  	}
   499  
   500  	if sig, err = kbcrypto.DecodeNaclSigInfoPacket(byt); err != nil {
   501  		return nil, kid, sigID, err
   502  	}
   503  	sigID = kbcrypto.ComputeSigIDFromSigBody(byt)
   504  	kid = sig.Kid.ToKID()
   505  	payload = sig.Payload
   506  	return payload, kid, sigID, nil
   507  }
   508  
   509  func SigAssertKbPayload(armored string, expected []byte) (sigID keybase1.SigIDBase, err error) {
   510  	var payload []byte
   511  	nilSigID := keybase1.SigIDBase("")
   512  	payload, _, sigID, err = SigExtractKbPayloadAndKID(armored)
   513  	if err != nil {
   514  		return nilSigID, err
   515  	}
   516  	if !FastByteArrayEq(expected, payload) {
   517  		return nilSigID, BadSigError{"wrong payload"}
   518  	}
   519  	return sigID, nil
   520  }
   521  
   522  // EncryptToString fails for this type of key.
   523  func (k NaclSigningKeyPair) EncryptToString(plaintext []byte, sender GenericKey) (ciphertext string, err error) {
   524  	err = KeyCannotEncryptError{}
   525  	return
   526  }
   527  
   528  // DecryptFromString fails for this type of key.
   529  func (k NaclSigningKeyPair) DecryptFromString(ciphertext string) (msg []byte, sender keybase1.KID, err error) {
   530  	err = KeyCannotDecryptError{}
   531  	return
   532  }
   533  
   534  // CanEncrypt always returns false for a signing key pair.
   535  func (k NaclSigningKeyPair) CanEncrypt() bool { return false }
   536  
   537  // CanDecrypt always returns false for a signing key pair.
   538  func (k NaclSigningKeyPair) CanDecrypt() bool { return false }
   539  
   540  // CanEncrypt always returns true for an encryption key pair.
   541  func (k NaclDHKeyPair) CanEncrypt() bool { return true }
   542  
   543  // CanDecrypt returns true if there's a private key available
   544  func (k NaclDHKeyPair) CanDecrypt() bool { return k.Private != nil }
   545  
   546  func (k NaclDHKeyPair) IsNil() bool {
   547  	var empty NaclDHKeyPublic
   548  	return bytes.Equal(k.Public[:], empty[:])
   549  }
   550  
   551  func (k NaclSigningKeyPair) IsNil() bool {
   552  	var empty kbcrypto.NaclSigningKeyPublic
   553  	return bytes.Equal(k.Public[:], empty[:])
   554  }
   555  
   556  // Encrypt a message to the key `k` from the given `sender`. If sender is nil, an ephemeral
   557  // keypair will be invented
   558  func (k NaclDHKeyPair) Encrypt(msg []byte, sender *NaclDHKeyPair) (*NaclEncryptionInfo, error) {
   559  	if sender == nil {
   560  		if tmp, err := GenerateNaclDHKeyPair(); err == nil {
   561  			sender = &tmp
   562  		} else {
   563  			return nil, err
   564  		}
   565  	} else if sender.Private == nil {
   566  		return nil, NoSecretKeyError{}
   567  	}
   568  
   569  	var nonce [NaclDHNonceSize]byte
   570  	if nRead, err := rand.Read(nonce[:]); err != nil {
   571  		return nil, err
   572  	} else if nRead != NaclDHNonceSize {
   573  		return nil, fmt.Errorf("Short random read: %d", nRead)
   574  	}
   575  
   576  	var ctext []byte
   577  	ctext = box.Seal(ctext, msg, &nonce, ((*[32]byte)(&k.Public)), ((*[32]byte)(sender.Private)))
   578  	ret := &NaclEncryptionInfo{
   579  		Ciphertext:     ctext,
   580  		EncryptionType: kbcrypto.KIDNaclDH,
   581  		Nonce:          nonce[:],
   582  		Receiver:       k.GetKID().ToBytes(),
   583  		Sender:         sender.GetKID().ToBytes(),
   584  	}
   585  
   586  	return ret, nil
   587  }
   588  
   589  // EncryptToString encrypts the plaintext using DiffieHelman; the this object is
   590  // the receiver, and the passed sender is optional.  If not provided, we'll make
   591  // up an ephemeral key.
   592  func (k NaclDHKeyPair) EncryptToString(plaintext []byte, sender GenericKey) (string, error) {
   593  	var senderDh *NaclDHKeyPair
   594  	if sender != nil {
   595  		var ok bool
   596  		if senderDh, ok = sender.(*NaclDHKeyPair); !ok {
   597  			return "", NoSecretKeyError{}
   598  		}
   599  	}
   600  
   601  	info, err := k.Encrypt(plaintext, senderDh)
   602  	if err != nil {
   603  		return "", err
   604  	}
   605  
   606  	return kbcrypto.EncodePacketToArmoredString(info)
   607  }
   608  
   609  func (k NaclDHKeyPair) SecretSymmetricKey(reason EncryptionReason) (NaclSecretBoxKey, error) {
   610  	if !k.CanDecrypt() {
   611  		return NaclSecretBoxKey{}, NoSecretKeyError{}
   612  	}
   613  
   614  	return deriveSymmetricKeyFromAsymmetric(*k.Private, reason)
   615  }
   616  
   617  // Derive a symmetric key using HMAC(k, reason).
   618  // Suitable for deriving from an asymmetric encryption key.
   619  // For deriving from a shared encryption key, this output is too close
   620  // to something that might be used as a public authenticator.
   621  func deriveSymmetricKeyFromAsymmetric(inKey NaclDHKeyPrivate, reason EncryptionReason) (NaclSecretBoxKey, error) {
   622  	var outKey = [32]byte{}
   623  	if len(reason) < encryptionReasonMinLength {
   624  		return outKey, KeyGenError{Msg: "reason must be at least 8 bytes"}
   625  	}
   626  
   627  	mac := hmac.New(sha256.New, inKey[:])
   628  	_, err := mac.Write(reason.Bytes())
   629  	if err != nil {
   630  		return outKey, err
   631  	}
   632  	out := mac.Sum(nil)
   633  
   634  	if copy(outKey[:], out) != len(outKey) {
   635  		return outKey, KeyGenError{Msg: "derived key of wrong size"}
   636  	}
   637  
   638  	return outKey, nil
   639  }
   640  
   641  // Derive a symmetric key.
   642  // Uses HMAC(key=reason, data=key)
   643  // Note the message and data are swapped as inputs to HMAC because that is less
   644  // likely to be accidentally used for another purpose such as authentication.
   645  func DeriveSymmetricKey(inKey NaclSecretBoxKey, reason EncryptionReason) (NaclSecretBoxKey, error) {
   646  	var outKey = [32]byte{}
   647  	if len(reason) < encryptionReasonMinLength {
   648  		return outKey, KeyGenError{Msg: "reason must be at least 8 bytes"}
   649  	}
   650  
   651  	mac := hmac.New(sha256.New, []byte(reason))
   652  	_, err := mac.Write(inKey[:])
   653  	if err != nil {
   654  		return outKey, err
   655  	}
   656  	out := mac.Sum(nil)
   657  
   658  	if copy(outKey[:], out) != len(outKey) {
   659  		return outKey, KeyGenError{Msg: "derived key of wrong size"}
   660  	}
   661  
   662  	return outKey, nil
   663  }
   664  
   665  // Derive a key from another.
   666  // Uses HMAC(key=key, data=reason)
   667  // Not to be confused with DeriveSymmetricKey which has hmac inputs swapped.
   668  // This one makes sense for derivation from secrets used only to derive from.
   669  func DeriveFromSecret(inKey [32]byte, reason DeriveReason) (outKey [32]byte, err error) {
   670  	if len(reason) < 8 {
   671  		return outKey, KeyGenError{Msg: "reason must be at least 8 bytes"}
   672  	}
   673  
   674  	mac := hmac.New(sha256.New, inKey[:])
   675  	_, err = mac.Write([]byte(reason))
   676  	if err != nil {
   677  		return outKey, err
   678  	}
   679  	out := mac.Sum(nil)
   680  
   681  	if copy(outKey[:], out) != len(outKey) {
   682  		return outKey, KeyGenError{Msg: "derived key of wrong size"}
   683  	}
   684  
   685  	return outKey, nil
   686  }
   687  
   688  func (k *NaclEncryptionInfo) GetTagAndVersion() (kbcrypto.PacketTag, kbcrypto.PacketVersion) {
   689  	return kbcrypto.TagEncryption, kbcrypto.KeybasePacketV1
   690  }
   691  
   692  // DecryptFromString decrypts the output of EncryptToString above,
   693  // and returns the kbcrypto.KID of the other end.
   694  func (k NaclDHKeyPair) DecryptFromString(ciphertext string) (msg []byte, sender keybase1.KID, err error) {
   695  	var nei NaclEncryptionInfo
   696  
   697  	if nei, err = DecodeArmoredNaclEncryptionInfoPacket(ciphertext); err != nil {
   698  		return
   699  	}
   700  
   701  	return k.Decrypt(&nei)
   702  }
   703  
   704  // Decrypt a NaclEncryptionInfo packet, and on success return the plaintext
   705  // and the kbcrypto.KID of the sender (which might be an ephemeral key).
   706  func (k NaclDHKeyPair) Decrypt(nei *NaclEncryptionInfo) (plaintext []byte, sender keybase1.KID, err error) {
   707  	if k.Private == nil {
   708  		err = NoSecretKeyError{}
   709  		return
   710  	}
   711  	if nei.EncryptionType != kbcrypto.KIDNaclDH {
   712  		err = DecryptBadPacketTypeError{}
   713  		return
   714  	}
   715  	var nonce [NaclDHNonceSize]byte
   716  	if len(nei.Nonce) != NaclDHNonceSize {
   717  		err = DecryptBadNonceError{}
   718  		return
   719  	}
   720  	copy(nonce[:], nei.Nonce)
   721  
   722  	var gk GenericKey
   723  	if gk, err = ImportKeypairFromKID(keybase1.KIDFromSlice(nei.Sender)); err != nil {
   724  		return
   725  	}
   726  
   727  	var senderDH NaclDHKeyPair
   728  	var ok bool
   729  	if senderDH, ok = gk.(NaclDHKeyPair); !ok {
   730  		err = DecryptBadSenderError{}
   731  		return
   732  	}
   733  
   734  	rkid := keybase1.KIDFromSlice(nei.Receiver)
   735  	if k.GetKID().NotEqual(rkid) {
   736  		err = DecryptWrongReceiverError{}
   737  		return
   738  	}
   739  
   740  	if plaintext, ok = box.Open(plaintext, nei.Ciphertext, &nonce,
   741  		((*[32]byte)(&senderDH.Public)), ((*[32]byte)(k.Private))); !ok {
   742  		err = DecryptOpenError{}
   743  		return
   744  	}
   745  	sender = senderDH.GetKID()
   746  	return
   747  }
   748  
   749  func GeneratePerUserKeySeed() (res PerUserKeySeed, err error) {
   750  	bs, err := RandBytes(32)
   751  	if err != nil {
   752  		return res, err
   753  	}
   754  	seed := PerUserKeySeed(MakeByte32(bs))
   755  	return seed, nil
   756  }
   757  
   758  func RandomNaclDHNonce() (nonce [NaclDHNonceSize]byte, err error) {
   759  	nRead, err := rand.Read(nonce[:])
   760  	if err != nil {
   761  		return nonce, err
   762  	}
   763  	if nRead != NaclDHNonceSize {
   764  		return nonce, fmt.Errorf("Short random read: %d", nRead)
   765  	}
   766  	return nonce, nil
   767  }