Pure Go implementation of the NaCL set of API's

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.

Owner
Kevin Burke
Formerly engineering at Twilio and Shyp. Now doing consulting, possibly for you. Get in touch!
Kevin Burke
Comments
  • 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.

  • 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.

  • 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

  • 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.

  • use stdlib ed25519

    use stdlib ed25519

  • 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?

  • 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.

  • 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..

NaCL Pipe Go Package

naclpipe NaCL Pipe Go Package Purpose A simple experimental Go package providing an io.Reader/io.Writer interface with an NaCL (pronounced 'Salt') cry

Sep 27, 2022
A pure-Go implementation of the CVE-2021-4034 PwnKit exploit

go-PwnKit A pure-Go implementation of the CVE-2021-4034 PwnKit exploit. Installation git clone [email protected]:OXDBXKXO/go-PwnKit.git cd go-PwnKit make

Nov 9, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Jan 6, 2023
Gorsair hacks its way into remote docker containers that expose their APIs
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

Dec 26, 2022
SPIRE is a toolchain of APIs for establishing trust between software systems across a wide variety of hosting platforms
SPIRE is a toolchain of APIs for establishing trust between software systems across a wide variety of hosting platforms

SPIRE (the SPIFFE Runtime Environment) is a toolchain of APIs for establishing trust between software systems across a wide variety of hosting platforms

Jan 2, 2023
set of web security test cases and a toolkit to construct new ones

Webseclab Webseclab contains a sample set of web security test cases and a toolkit to construct new ones. It can be used for testing security scanners

Jan 7, 2023
Hotdog is a set of OCI hooks used to inject the Log4j Hot Patch into containers.

Hotdog Hotdog is a set of OCI hooks used to inject the Log4j Hot Patch into containers. How it works When runc sets up the container, it invokes hotdo

Nov 12, 2022
This repository intends to have a set of tools to take advantage of features on the Burp Enterprise

This repository intends to have a set of tools to take advantage of features on the Burp Enterprise

Jan 22, 2022
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

Dec 10, 2022
CVE-2021-4034 - A Golang implementation of clubby789's implementation of CVE-2021-4034

CVE-2021-4034 January 25, 2022 | An00bRektn This is a golang implementation of C

Feb 3, 2022
Implementation of io/fs.FS that appends SHA256 hashes to filenames to allow for aggressive HTTP caching.

hashfs Implementation of io/fs.FS that appends SHA256 hashes to filenames to allow for aggressive HTTP caching.

Dec 1, 2022
A Go language implementation of the proposed ads.cert protocols for integration in programmatic ads solutions.

go-adscert A Go language implementation of the proposed ads.cert protocols for integration in programmatic ads solutions. This repository is a work-in

Jun 4, 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

Dec 30, 2022
Consistent hashing hashring implementation.

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

Nov 11, 2022
Implementation of Secret Service API

Secret Service Implementation of Secret Service API What does this project do? By using secret service, you don't need to use KeePassXC secretservice

Dec 21, 2022
Implementation of polynomial KZG proofs and 257-ary verkle trie
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

Dec 14, 2022
Shellcode implementation of Reflective DLL Injection by Golang. Convert DLLs to position independent shellcode
Shellcode implementation of Reflective DLL Injection by Golang. Convert DLLs to position independent shellcode

?? Frog For Automatic Scan ?? Doge For Defense Evasion&Offensive Security Doge-sRDI Shellcode implementation of Reflective DLL Injection by Golang. Co

Dec 8, 2022
Coraza Server is the most ambitious implementation of Coraza WAF

Coraza Server is the most ambitious implementation of Coraza WAF, it's designed to integrate with systems written in different languages, like C, using multiple protocols like SPOA, REST and GRPC.

Dec 29, 2022
Exploratory implementation of the Eva virtual machine

Eva Exploratory implementation of the Eva virtual machine in pure Go. Eva is a simple virtual machine designed for educational use. This is not intend

Dec 27, 2021