Pure Go implementation of the NaCL set of API's

Overview

go-nacl

GoDoc

This is a pure Go implementation of the API's available in NaCL: https://nacl.cr.yp.to. Compared with the implementation in golang.org/x/crypto/nacl, this library offers all of the API's present in NaCL, better compatibility with NaCL implementations written in other languages, as well as some utilities for generating and loading keys and nonces, and encrypting messages.

Many of them are simple wrappers around functions or libraries available in the Go standard library, or in the golang.org/x/crypto package. Other code I copied directly into this library with the appropriate LICENSE; if a function is longer than, say, 5 lines, I didn't write it myself. There are no dependencies outside of the standard library or golang.org/x/crypto.

The goal is to both show how to implement the NaCL functions in pure Go, and to provide interoperability between messages encrypted/hashed/authenticated in other languages, and available in Go.

Among other benefits, NaCL is designed to be misuse resistant and standardizes on the use of 32 byte keys and 24 byte nonces everywhere. Several helpers are present for generating keys/nonces and loading them from configuration, as well as for encrypting messages. You can generate a key by running openssl rand -hex 32 and use the helpers in your program like so:

import "github.com/kevinburke/nacl"
import "github.com/kevinburke/nacl/secretbox"

func main() {
    key, err := nacl.Load("6368616e676520746869732070617373776f726420746f206120736563726574")
    if err != nil {
        panic(err)
    }
    encrypted := secretbox.EasySeal([]byte("hello world"), key)
    fmt.Println(base64.StdEncoding.EncodeToString(encrypted))
}

The package names match the primitives available in NaCL, with the crypto_ prefix removed. Some function names have been changed to match the Go conventions.

Installation

go get github.com/kevinburke/nacl

Or you can Git clone the code directly to $GOPATH/src/github.com/kevinburke/nacl.

Who am I?

While you probably shouldn't trust random security code from the Internet, I'm reasonably confident that this code is secure. I did not implement any of the hard math (poly1305, XSalsa20, curve25519) myself - I call into golang.org/x/crypto for all of those functions. I also ported over every test I could find from the C/C++ code, and associated RFC's, and ensured that these libraries passed those tests.

I'm a contributor to the Go Standard Library and associated tools, and I've also been paid to do security consulting for startups, and found security problems in consumer sites.

Errata

  • The implementation of crypto_sign uses the ref10 implementation of ed25519 from SUPERCOP, not the current implementation in NaCL. The difference is that the entire 64-byte signature is prepended to the message; in the current version of NaCL, separate bits are prepended and appended to the message.

  • Compared with crypto/ed25519, this library's Sign implementation returns the message along with the signature, and Verify expects the first 64 bytes of the message to be the signature. This simplifies the API and matches the behavior of the ref10 implementation and other NaCL implementations. Sign also flips the order of the message and the private key: Sign(message, privatekey), to match the NaCL implementation.

  • Compared with golang.org/x/crypto/nacl/box, Precompute returns the shared key instead of modifying the input. In several places the code was modified to call functions that now exist in nacl.

  • Compared with golang.org/x/crypto/nacl/secretbox, Seal and Open call the onetimeauth package in this library, instead of calling golang.org/x/crypto/poly1305 directly.

Issues
  • Timing attacks

    Timing attacks

    Given that the library does not seem to protect against timing attacks it would probably be a good idea to mention that prevention of such attacks is left up to the consumer of the lib. Seems worth adding to the readme/ documentation.

    opened by insanitybit 5
  • support Ed25519 to Curve25519 keys conversion

    support Ed25519 to Curve25519 keys conversion

    This should be very useful, such as https://download.libsodium.org/doc/advanced/ed25519-curve25519.html

    golang has such plan, but seems like no progress. https://github.com/golang/go/issues/20504

    opened by leslie-wang 2
  • Nonce operation advice

    Nonce operation advice

    Sorry if this generic crypto question is out of scope.

    What nonce operation mode would you suggest for a stateful message exchange protocol built on top of secretbox? I can imagine at least two options:

    • generate random nonce in every message, send length and nonce in authenticated clear text
    • hello message as above with another secret nonce in payload, derive all next nonces from that secret payload, send only authenticated length in clear text

    My use case is RPC with messages around 50-200 bytes on expensive 3g network, and shaving 24 bytes from each message is definitely worth pursuing.

    Thanks for your time.

    opened by temoto 2
  • foo bar

    foo bar

    null

    opened by kevinburke 1
  • Add godoc button to readme

    Add godoc button to readme

    Add a godoc button to the readme for easy access

    opened by nijaru 1
  • use stdlib ed25519

    use stdlib ed25519

    opened by bsdlp 1
  • Open function issue after EasySeal or Seal

    Open function issue after EasySeal or Seal

    Hi,

    I have some doubts about how the piece of code 1 works and the 2 does not. I do not think that this was a real issue.

    • Code 1:
    package main
    
    import (
    	crypto_rand "crypto/rand"
    	"encoding/base64"
    	"fmt"
    	"github.com/kevinburke/nacl/box"
    )
    
    func main() {
    	pk, sk, err := box.GenerateKey(crypto_rand.Reader)
    	if err != nil {
    		panic(err)
    	}
    	message := "the sky is blue"
    	fmt.Printf("Plaintext message: %s\n", message)
    	
    	enc := box.EasySeal([]byte(message), pk, sk)
    	fmt.Printf("Encrypted message: %s\n", base64.StdEncoding.EncodeToString(enc))
    	
    	dec, _ := box.EasyOpen(enc, pk, sk)
    	fmt.Printf("Decrypted message: %s\n", string(dec))
    }
    

    The result of code 1 is the following:

    Plaintext message: the sky is blue
    Encrypted message: E/QEV7B64zDkcu4+1BwJmd7juRG8cfl9NDVd/OYuC7xUWr0rkoQFOvHUsBapJqypYZAC2x71iw==
    Decrypted message: the sky is blue
    
    • Code 2:
    package main
    
    import (
    	crypto_rand "crypto/rand"
    	"encoding/base64"
    	"fmt"
    
    	"github.com/kevinburke/nacl"
    	"github.com/kevinburke/nacl/box"
    )
    
    func main() {
    	pk, sk, err := box.GenerateKey(crypto_rand.Reader)
    	if err != nil {
    		panic(err)
    	}
    	message := "the sky is blue"
    	fmt.Printf("Plaintext message: %s\n", message)
    
    	// Encrypt
    	nonce := nacl.NewNonce()
    	var out []byte
    
    	enc := box.Seal(out, []byte(message), nonce, pk, sk)
    	fmt.Printf("Encrypted message: %s\n", base64.StdEncoding.EncodeToString(enc))
    
    	// Decrypt
    	//decNonce := new([nacl.NonceSize]byte)
    	//copy(decNonce[:], message[:24])
    
    	dec, _ := box.EasyOpen(enc, pk, sk)
    	fmt.Printf("Decrypted message: %s\n", string(dec))
    }
    

    The result of code 1 is the following:

    Plaintext message: the sky is blue
    Encrypted message: KTdHagkeX6Il61uiTbCzvAqpAx4XUfr3BYhVGElPLA==
    Decrypted message: 
    

    Am I missing something when Seal() is called?

    opened by jfagoagas 0
  • switch to using Filippo's ed25519 library

    switch to using Filippo's ed25519 library

    we should switch to using it instead of using the x/crypto one.

    opened by kevinburke 0
  • What if I need to use rsa 2048 bit key?

    What if I need to use rsa 2048 bit key?

    With python lib for NaCl it's possible, but as I see it isn't with this library. What should I do?

    opened by Numenorean 0
  • use go.mod, declare a version of the API

    use go.mod, declare a version of the API

    pkg.go.dev is pushing for packages to

    • Declare dependencies in go.mod
    • Tag a v1
    opened by indrora 1
  • More help with nonce generation in box.Easy*

    More help with nonce generation in box.Easy*

    See https://buttondown.email/cryptography-dispatches/archive/59c99d2e-9fd7-4859-934b-f52cf254e6b2 and https://github.com/golang/go/issues/43148#issuecomment-743738586.

    opened by kevinburke 0
  • Allow users to pass in their own byte arrays

    Allow users to pass in their own byte arrays

    For example, the base64 api's have a user pass in a dst array to decode into. The nacl API's in golang.org/x/crypto follow a similar pattern.

    The advantage of doing it this way is that it reduces allocations, which helps performance.

    The disadvantage is that it requires the caller to know more about how the API works, and ensure they bring along a byte array that's large enough.

    The C/C++ API's have it both ways. The C++ API's return a byte array, the C API's require you to pass one in, but I think the latter is because you can only return integers from C functions..

    opened by kevinburke 2
Owner
Kevin Burke
Formerly engineering at Twilio and Shyp. Now doing consulting, possibly for you. Get in touch!
Kevin Burke
a modern crypto messaging format

saltpack a modern crypto messaging format https://saltpack.org/ saltpack is a streamlined, modern solution, designed with simplicity in mind. It is ea

Keybase 907 Jul 9, 2021
Community-run technology powering the cryptocurrency, and decentralized applications on TrustFi Network

Go TrustFi-Ethereum Official Golang implementation of the TrustFi-Ethereum protocol. Automated builds are available for stable releases and the unstab

TrustFi Network 786 May 26, 2021
Yet another Binance Smart Chain client based on TrustFi Network

TrustFi Smart Chain The goal of TrustFi Smart Chain is to bring programmability and interoperability to Binance Chain. In order to embrace the existin

TrustFi Network 19 Dec 23, 2019
The minilock file encryption system, ported to pure Golang. Includes CLI utilities.

Go-miniLock A pure-Go reimplementation of the miniLock asymmetric encryption system. by Cathal Garvey, Copyright Oct. 2015, proudly licensed under the

Cathal Garvey 173 May 11, 2021
sops is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP

sops is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP. (demo)

Mozilla 7.9k Jul 17, 2021
The bare metal Go smart card

Authors Andrea Barisani [email protected] | [email protected] Introduction The GoKey application implements a USB smartcard in pure Go

F-Secure Foundry 106 Jul 13, 2021
Pure Go Kerberos library for clients and services

gokrb5 It is recommended to use the latest version: Development will be focused on the latest major version. New features will only be targeted at thi

Jonathan Turner 515 Jul 16, 2021
null 33 Jul 9, 2021
This repo is some SDK of Binance

Binance API Go Language SDK This is a Binance Go language sdk that uses a method similar to HuobiRDCenter/huobi_Golang Official Documents Please make

Mickey (Ah !) 591 Jun 1, 2021
DERO Homomorphic Encryption Blockchain Protocol

Homomorphic encryption is a form of encryption allowing one to perform calculations on encrypted data without decrypting it first. The result of the computation is in an encrypted form, when decrypted the output is the same as if the operations had been performed on the unencrypted data.

null 30 Jul 25, 2021
Merchant API reference implementation

mAPI More details available in the BRFC Spec for Merchant API. The old golang (v1.1) implementation is no longer being maintained and has been moved t

Bitcoin SV 11 Jun 24, 2021
Windows helpers for GnuPG tools suite - OpenSSH, WSL 1, WSL2, Cygwin, MSYS2, Git4Windows, Putty...

win-gpg-agent Simple set of tools to make working with GPG and SSH keys easier on Windows 10. Windows 10 has ssh-agent service (with support for persi

rupor 54 Jul 9, 2021
`age-plugin-yubikey` implementation, encrypt things with a Yubikey/any PIV card

This is an age plugin for PIV cards/Yubikey. Your secret is kept safe on the tamperproof hardware, while letting you use the age command-line.

Tv 18 Jul 16, 2021
DERO: Secure, Anonymous Blockchain with Smart Contracts. Subscribe to Dero announcements by sending mail to [email protected] with subject: subscribe announcements

Welcome to the Dero Project DERO News Forum Wiki Explorer Source Twitter Discord Github Stats WebWallet Medium Table of Contents ABOUT DERO PROJECT DE

null 231 Jul 13, 2021