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 }