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  }