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 golang.org/x/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
  • Verify that the message was signed with public key

    Verify that the message was signed with public key

    Hello! Thanks for the library.

    TweetNaCl has a method which verifies that the given message was signed with given PublicKey:

    nacl.sign.detached.verify = function(msg, sig, publicKey) {
    

    Is there something similar in this library?

    I saw this method but it doesn't take the message into account. I'd like to verify there's a specific nonce present in a message.

    opened by dn-l 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
Container Signing

cosign Container Signing, Verification and Storage in an OCI registry. Cosign aims to make signatures invisible infrastructure. Info Cosign is develop

sigstore 1.1k Oct 24, 2021
Implementation of polynomial KZG proofs and 257-ary verkle trie

257-ary verkle trie Disclaimer: the code in this package is experimental. It can only be used in research and is not suitable for use in production. T

Evaldas Drasutis 3 Sep 6, 2021
Lightweight static analysis for many languages. Find bug variants with patterns that look like source code.

Lightweight static analysis for many languages. Find bugs and enforce code standards. Semgrep is a fast, open-source, static analysis tool that finds

r2c 5.4k Oct 25, 2021
A fully self-contained Nmap like parallel port scanning module in pure Golang that supports SYN-ACK (Silent Scans)

gomap What is gomap? Gomap is a fully self-contained nmap like module for Golang. Unlike other projects which provide nmap C bindings or rely on other

jtimperio 31 Oct 10, 2021
PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. You can use PHP like functions in your app, module etc. when you add this module to your project.

PHP Functions for Golang - phpfuncs PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. Y

Serkan Algur 42 Aug 19, 2021
Automatic HTTPS for any Go program: fully-managed TLS certificate issuance and renewal

Easy and Powerful TLS Automation The same library used by the Caddy Web Server Caddy's automagic TLS features—now for your own Go programs—in one powe

Caddy 3.8k Oct 21, 2021
HTTP middleware for Go that facilitates some quick security wins.

Secure Secure is an HTTP middleware for Go that facilitates some quick security wins. It's a standard net/http Handler, and can be used with many fram

Cory Jacobsen 1.8k Oct 21, 2021
ID hashing and Obfuscation using Knuth's Algorithm

ID Obfuscation/Hashing Transformer for Go There are many times when you want to generate obfuscated ids. This package utilizes Knuth's Hashing Algorit

pj 288 Oct 13, 2021
Gorsair hacks its way into remote docker containers that expose their APIs

Gorsair Gorsair is a penetration testing tool for discovering and remotely accessing Docker APIs from vulnerable Docker containers. Once it has access

Brendan Le Glaunec 733 Oct 11, 2021
DockerSlim (docker-slim): Don't change anything in your Docker container image and minify it by up to 30x (and for compiled languages even more) making it secure too! (free and open source)

Minify and Secure Docker containers (free and open source!) Don't change anything in your Docker container image and minify it by up to 30x making it

docker-slim 10.9k Oct 24, 2021
An authorization library that supports access control models like ACL, RBAC, ABAC in Golang

Casbin News: still worry about how to write the correct Casbin policy? Casbin online editor is coming to help! Try it at: https://casbin.org/editor/ C

Casbin 10.5k Oct 23, 2021
How to systematically secure anything: a repository about security engineering

How to Secure Anything Security engineering is the discipline of building secure systems. Its lessons are not just applicable to computer security. In

Veeral Patel 6.4k Oct 17, 2021
Ah shhgit! Find secrets in your code. Secrets detection for your GitHub, GitLab and Bitbucket repositories: www.shhgit.com

shhgit helps secure forward-thinking development, operations, and security teams by finding secrets across their code before it leads to a security br

Paul 3.3k Oct 25, 2021
golang uuid-shellcode加载器,分离执行,可直接把shellcode写入程序。

golang uuid-shellcode加载器,分离执行,可直接把shellcode写入程序。

Try 8 Aug 25, 2021
Consistent hashing hashring implementation.

hashring Consistent hashing hashring implementation. Overview This is an implementation of the consistent hashing hashring data structure. In general,

Sergey Kamardin 26 Sep 22, 2021
Cameradar hacks its way into RTSP videosurveillance cameras

Cameradar An RTSP stream access tool that comes with its library Cameradar allows you to Detect open RTSP hosts on any accessible target host Detect w

Brendan Le Glaunec 2.7k Oct 24, 2021
A tool to check for vulnerabilities in your Golang dependencies, powered by Sonatype OSS Index

Nancy nancy is a tool to check for vulnerabilities in your Golang dependencies, powered by Sonatype OSS Index, and as well, works with Nexus IQ Server

Sonatype Community 328 Oct 21, 2021
Secure software enclave for storage of sensitive information in memory.

MemGuard Software enclave for storage of sensitive information in memory. This package attempts to reduce the likelihood of sensitive data being expos

Awn 2k Oct 18, 2021
Password generator written in Go

go-generate-password Password generator written in Go. Use as a library or as a CLI. Usage CLI go-generate-password can be used on the cli, just insta

Miles Croxford 28 Oct 13, 2021