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