github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/signencrypt/example/main.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/hex"
     5  	"io"
     6  	"log"
     7  	"os"
     8  	"strconv"
     9  
    10  	docopt "github.com/docopt/docopt-go"
    11  	"github.com/keybase/client/go/chat/signencrypt"
    12  	"github.com/keybase/client/go/kbcrypto"
    13  	"github.com/keybase/go-crypto/ed25519"
    14  )
    15  
    16  func failf(format string, args ...interface{}) {
    17  	log.Printf(format, args...)
    18  	os.Exit(1)
    19  }
    20  
    21  func decodeHexArg(arg string) []byte {
    22  	decoded, err := hex.DecodeString(arg)
    23  	if err != nil {
    24  		failf("'%s' is not valid hex: %s", arg, err)
    25  	}
    26  	return decoded
    27  }
    28  
    29  func zeroSecretboxKey() signencrypt.SecretboxKey {
    30  	var key [signencrypt.SecretboxKeySize]byte // all zeroes
    31  	return &key
    32  }
    33  
    34  func zeroNonce() signencrypt.Nonce {
    35  	var nonce [signencrypt.NonceSize]byte // all zeroes
    36  	return &nonce
    37  }
    38  
    39  func zeroVerifyKey() signencrypt.VerifyKey {
    40  	var key [ed25519.PublicKeySize]byte
    41  	// Generated from libsodium's crypto_sign_seed_keypair with a zero seed.
    42  	copy(key[:], ";j'\xbc\xce\xb6\xa4-b\xa3\xa8\xd0*o\rse2\x15w\x1d\xe2C\xa6:\xc0H\xa1\x8bY\xda)")
    43  	return &key
    44  }
    45  
    46  func zeroSignKey() signencrypt.SignKey {
    47  	var key [ed25519.PrivateKeySize]byte
    48  	// Generated from libsodium's crypto_sign_seed_keypair with a zero seed.
    49  	copy(key[:], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;j'\xbc\xce\xb6\xa4-b\xa3\xa8\xd0*o\rse2\x15w\x1d\xe2C\xa6:\xc0H\xa1\x8bY\xda)")
    50  	return &key
    51  }
    52  
    53  func seal(enckey signencrypt.SecretboxKey, signkey signencrypt.SignKey, signaturePrefix kbcrypto.SignaturePrefix, nonce signencrypt.Nonce, chunklen int64) error {
    54  	encoder := signencrypt.NewEncoder(enckey, signkey, signaturePrefix, nonce)
    55  	if chunklen != 0 {
    56  		encoder.ChangePlaintextChunkLenForTesting(chunklen)
    57  	}
    58  	var buf [4096]byte
    59  	for {
    60  		num, err := os.Stdin.Read(buf[:])
    61  		if err == io.EOF {
    62  			break
    63  		} else if err != nil {
    64  			return err
    65  		}
    66  		encoded := encoder.Write(buf[0:num])
    67  		_, err = os.Stdout.Write(encoded)
    68  		if err != nil {
    69  			return err
    70  		}
    71  	}
    72  	encoded := encoder.Finish()
    73  	_, err := os.Stdout.Write(encoded)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	return nil
    78  }
    79  
    80  func open(enckey signencrypt.SecretboxKey, verifykey signencrypt.VerifyKey, signaturePrefix kbcrypto.SignaturePrefix, nonce signencrypt.Nonce, chunklen int64) error {
    81  	decoder := signencrypt.NewDecoder(enckey, verifykey, signaturePrefix, nonce)
    82  	if chunklen != 0 {
    83  		decoder.ChangePlaintextChunkLenForTesting(chunklen)
    84  	}
    85  	var buf [4096]byte
    86  	for {
    87  		num, err := os.Stdin.Read(buf[:])
    88  		if err == io.EOF {
    89  			break
    90  		} else if err != nil {
    91  			return err
    92  		}
    93  		decoded, err := decoder.Write(buf[0:num])
    94  		if err != nil {
    95  			return err
    96  		}
    97  		_, err = os.Stdout.Write(decoded)
    98  		if err != nil {
    99  			return err
   100  		}
   101  	}
   102  	decoded, err := decoder.Finish()
   103  	if err != nil {
   104  		return err
   105  	}
   106  	_, err = os.Stdout.Write(decoded)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	return nil
   111  }
   112  
   113  func main() {
   114  	usage := `Usage:
   115      example seal [--enckey=<enckey>] [--signkey=<signkey>]
   116                   [--sigprefix=<sigprefix>] [--nonce=<nonce>] [--chunklen=<chunklen>]
   117      example open [--enckey=<enckey>] [--verifykey=<signkey>]
   118                   [--sigprefix=<sigprefix>] [--nonce=<nonce>] [--chunklen=<chunklen>]
   119  
   120  Options:
   121      --enckey=<enckey>        the 32-byte encryption key (in hex)
   122      --signkey=<signkey>      the 64-byte signing private key (in hex)
   123      --verifykey=<verifykey>  the 32-byte signing public  key (in hex)
   124      --sigprefix=<sigprefix>  the signature prefix (string)
   125      --nonce=<nonce>          the 16-byte nonce
   126      --chunklen=<chunklen>    the size of plaintext chunks, for testing, default 2^20 bytes
   127  `
   128  	arguments, _ := docopt.Parse(usage, nil, true, "signencrypt crypto example", false)
   129  
   130  	enckey := zeroSecretboxKey()
   131  	if arguments["--enckey"] != nil {
   132  		copy(enckey[:], decodeHexArg(arguments["--enckey"].(string)))
   133  	}
   134  
   135  	signkey := zeroSignKey()
   136  	if arguments["--signkey"] != nil {
   137  		copy(signkey[:], decodeHexArg(arguments["--signkey"].(string)))
   138  	}
   139  
   140  	verifykey := zeroVerifyKey()
   141  	if arguments["--verifykey"] != nil {
   142  		copy(verifykey[:], decodeHexArg(arguments["--verifykey"].(string)))
   143  	}
   144  
   145  	signaturePrefix := kbcrypto.SignaturePrefixTesting
   146  	if arguments["--sigprefix"] != nil {
   147  		signaturePrefixStr := arguments["--sigprefix"].(string)
   148  		signaturePrefix = kbcrypto.SignaturePrefix(signaturePrefixStr)
   149  	}
   150  
   151  	nonce := zeroNonce()
   152  	if arguments["--nonce"] != nil {
   153  		copy(nonce[:], decodeHexArg(arguments["--nonce"].(string)))
   154  	}
   155  
   156  	var chunklen int64
   157  	if arguments["--chunklen"] != nil {
   158  		parsed, err := strconv.Atoi(arguments["--chunklen"].(string))
   159  		if err != nil {
   160  			failf("error converting: %s", err)
   161  		}
   162  		chunklen = int64(parsed)
   163  	}
   164  
   165  	var err error
   166  	if arguments["seal"].(bool) {
   167  		err = seal(enckey, signkey, signaturePrefix, nonce, chunklen)
   168  	} else {
   169  		err = open(enckey, verifykey, signaturePrefix, nonce, chunklen)
   170  	}
   171  	if err != nil {
   172  		failf("crypto error: %s", err)
   173  	}
   174  }