github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbcrypto/nacl_signing_key.go (about) 1 // Copyright 2018 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package kbcrypto 5 6 import ( 7 "encoding/base64" 8 9 keybase1 "github.com/keybase/client/go/protocol/keybase1" 10 "github.com/keybase/go-crypto/ed25519" 11 ) 12 13 type NaclSignature [ed25519.SignatureSize]byte 14 15 type NaclSigningKeyPublic [ed25519.PublicKeySize]byte 16 17 func (k NaclSigningKeyPublic) Verify(msg []byte, sig NaclSignature) bool { 18 return ed25519.Verify(k[:], msg, sig[:]) 19 } 20 21 const ( 22 KeybaseKIDV1 = 1 // Uses SHA-256 23 ) 24 25 const ( 26 IDSuffixKID = 0x0a 27 ) 28 29 func (k NaclSigningKeyPublic) GetBinaryKID() keybase1.BinaryKID { 30 prefix := []byte{ 31 byte(KeybaseKIDV1), 32 byte(KIDNaclEddsa), 33 } 34 suffix := byte(IDSuffixKID) 35 out := prefix 36 out = append(out, k[:]...) 37 out = append(out, suffix) 38 return keybase1.BinaryKID(out) 39 } 40 41 func (k NaclSigningKeyPublic) GetKID() keybase1.KID { 42 return k.GetBinaryKID().ToKID() 43 } 44 45 func KIDToNaclSigningKeyPublic(bk []byte) *NaclSigningKeyPublic { 46 if len(bk) != 3+ed25519.PublicKeySize { 47 return nil 48 } 49 if bk[0] != byte(KeybaseKIDV1) || bk[1] != byte(KIDNaclEddsa) || bk[len(bk)-1] != byte(IDSuffixKID) { 50 return nil 51 } 52 var ret NaclSigningKeyPublic 53 copy(ret[:], bk[2:len(bk)-1]) 54 return &ret 55 } 56 57 type NaclSigningKeyPrivate [ed25519.PrivateKeySize]byte 58 59 func (k NaclSigningKeyPrivate) Sign(msg []byte) NaclSignature { 60 var sig NaclSignature 61 copy(sig[:], ed25519.Sign(k[:], msg)) 62 return sig 63 } 64 65 func (k NaclSigningKeyPrivate) SignInfoV0(msg []byte, public NaclSigningKeyPublic) NaclSigInfo { 66 // Version 0 is just over the unprefixed message (assume version 0 if no version present) 67 // Version 1 is the same. 68 return NaclSigInfo{ 69 Kid: public.GetBinaryKID(), 70 Payload: msg, 71 Sig: k.Sign(msg), 72 SigType: SigKbEddsa, 73 HashType: HashPGPSha512, 74 Detached: true, 75 Version: 0, 76 } 77 } 78 79 func (k NaclSigningKeyPrivate) SignToStringV0(msg []byte, public NaclSigningKeyPublic) (string, keybase1.SigIDBase, error) { 80 naclSig := k.SignInfoV0(msg, public) 81 82 body, err := EncodePacketToBytes(&naclSig) 83 if err != nil { 84 return "", "", err 85 } 86 87 sig := base64.StdEncoding.EncodeToString(body) 88 id := ComputeSigIDFromSigBody(body) 89 return sig, id, nil 90 } 91 92 type BadSignaturePrefixError struct{} 93 94 func (e BadSignaturePrefixError) Error() string { return "bad signature prefix" } 95 96 func (k NaclSigningKeyPrivate) SignInfoV2(msg []byte, public NaclSigningKeyPublic, prefix SignaturePrefix) (NaclSigInfo, error) { 97 if prefix.HasNullByte() || len(prefix) == 0 { 98 return NaclSigInfo{}, BadSignaturePrefixError{} 99 } 100 101 // Version 0 is just over the unprefixed message (assume version 0 if no version present) 102 // Version 1 is the same. 103 return NaclSigInfo{ 104 Kid: public.GetBinaryKID(), 105 Payload: msg, 106 Sig: k.Sign(prefix.Prefix(msg)), 107 SigType: SigKbEddsa, 108 HashType: HashPGPSha512, 109 Detached: true, 110 Version: 2, 111 Prefix: prefix, 112 }, nil 113 }