func doKeyInfo() { b, err := ioutil.ReadFile(*kiFilename) log.Fatale(err, "cannot read keyfile") var sk [64]byte isPrivate, err := spki.LoadKeyFile(bytes.NewReader(b), &sk) log.Fatale(err, "cannot decode keyfile") if isPrivate { fmt.Fprintf(os.Stderr, ";; Ed25519 Private Key\n") } else { fmt.Fprintf(os.Stderr, ";; Ed25519 Public Key\n") } fmt.Fprintf(os.Stderr, ";; Fingerprint: %v\n", hexFormat(sk[32:64])) fmt.Fprintf(os.Stderr, ";; Fingerprint (b32): %v\n", spki.EncodeB32(sk[32:64])) fmt.Fprintf(os.Stderr, "%s", prefix(randomart.Generate(sk[32:64], " Ed25519").String())) var cpk [32]byte var edpub [32]byte copy(edpub[:], sk[32:64]) if !extra25519.PublicKeyToCurve25519(&cpk, &edpub) { log.Fatal("Cannot derive Curve25519 public key.") } fmt.Fprintf(os.Stderr, ";; Curve25519 Fingerprint: %v\n", hexFormat(cpk[:])) fmt.Fprintf(os.Stderr, ";; Curve25519 Fingerprint (b32): %v\n", spki.EncodeB32(cpk[:])) }
func TestKeys(t *testing.T) { var cpriv, cpub, cpub2 [32]byte pub, priv, err := ed25519.GenerateKey(rand.Reader) if assert.NoError(t, err) { assert.True(t, extra25519.PublicKeyToCurve25519(&cpub, pub), "Calling PublicKeyToCurve25519 failed") extra25519.PrivateKeyToCurve25519(&cpriv, priv) curve25519.ScalarBaseMult(&cpub2, &cpriv) assert.Equal(t, cpub, cpub2) } }
// loadOrGenerateKeys reads the master signing key from the global // state in DB, (generating one if it's not already there), and // generates the boxing keys based on it. // // This is meant to be called exactly once at startup time. func loadOrGenerateKeys(db *bolt.DB) (*CryptoKeys, error) { var k CryptoKeys getKey := func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(tokens.BucketBazil)) val := bucket.Get([]byte(tokens.GlobalStateKey)) if val == nil { // have not generated a key yet return nil } if len(val) != ed25519.PrivateKeySize { return fmt.Errorf("master key wrong is the wrong size: length=%d", len(val)) } var sigPriv [ed25519.PrivateKeySize]byte copy(sigPriv[:], val) k.Sign.Priv = &sigPriv return nil } if err := db.View(getKey); err != nil { return nil, err } if k.Sign.Priv == nil { // did not load keys from database var err error _, signPriv, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } k.Sign.Priv = signPriv // save it for future runs putKey := func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(tokens.BucketBazil)) return bucket.Put([]byte(tokens.GlobalStateKey), signPriv[:]) } if err := db.Update(putKey); err != nil { return nil, err } } k.Sign.Pub = extractEd25519Pubkey(k.Sign.Priv) // generate other keys from it k.Box.Priv = &[32]byte{} extra25519.PrivateKeyToCurve25519(k.Box.Priv, k.Sign.Priv) k.Box.Pub = &[32]byte{} extra25519.PublicKeyToCurve25519(k.Box.Pub, k.Sign.Pub) return &k, nil }
func (contact *Contact) processKeyExchange(kxsBytes []byte, testing, simulateOldClient, disableV2Ratchet bool) error { var kxs pond.SignedKeyExchange if err := proto.Unmarshal(kxsBytes, &kxs); err != nil { return err } var sig [64]byte if len(kxs.Signature) != len(sig) { return errors.New("invalid signature length") } copy(sig[:], kxs.Signature) var kx pond.KeyExchange if err := proto.Unmarshal(kxs.Signed, &kx); err != nil { return err } if len(kx.PublicKey) != len(contact.theirPub) { return errors.New("invalid public key") } copy(contact.theirPub[:], kx.PublicKey) if !ed25519.Verify(&contact.theirPub, kxs.Signed, &sig) { return errors.New("invalid signature") } contact.theirServer = *kx.Server if _, _, err := parseServer(contact.theirServer, testing); err != nil { return err } group, ok := new(bbssig.Group).Unmarshal(kx.Group) if !ok { return errors.New("invalid group") } if contact.myGroupKey, ok = new(bbssig.MemberKey).Unmarshal(group, kx.GroupKey); !ok { return errors.New("invalid group key") } if len(kx.IdentityPublic) != len(contact.theirIdentityPublic) { return errors.New("invalid public identity") } copy(contact.theirIdentityPublic[:], kx.IdentityPublic) if simulateOldClient { kx.Dh1 = nil } if len(kx.Dh1) == 0 { // They are using an old-style ratchet. We have to extract the // private value from the Ratchet in order to use it with the // old code. contact.lastDHPrivate = contact.ratchet.GetKXPrivateForTransition() if len(kx.Dh) != len(contact.theirCurrentDHPublic) { return errors.New("invalid public DH value") } copy(contact.theirCurrentDHPublic[:], kx.Dh) contact.ratchet = nil } else { // If the identity and ed25519 public keys are the same (modulo // isomorphism) then the contact is using the v2 ratchet. var ed25519Public, curve25519Public [32]byte copy(ed25519Public[:], kx.PublicKey) extra25519.PublicKeyToCurve25519(&curve25519Public, &ed25519Public) v2 := !disableV2Ratchet && bytes.Equal(curve25519Public[:], kx.IdentityPublic[:]) if err := contact.ratchet.CompleteKeyExchange(&kx, v2); err != nil { return err } } contact.generation = *kx.Generation return nil }