session.go 2.41 KB
Newer Older
Jordan Sissel's avatar
.  
Jordan Sissel committed
1 2
package sodium 
// #include <sodium.h>
3
// #cgo pkg-config: sodium
Jordan Sissel's avatar
.  
Jordan Sissel committed
4 5
import "C"
import "unsafe"
6
import "fmt"
Jordan Sissel's avatar
.  
Jordan Sissel committed
7 8 9 10 11 12 13 14 15 16

type Session struct {
  // the public key of the agent who is sending you encrypted messages
  Public [PUBLICKEYBYTES]byte 

  // your secret key
  Secret [SECRETKEYBYTES]byte

  // for beforenm/afternm optimization
  k [crypto_box_BEFORENMBYTES]byte
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
17 18

  // The nonce generator.
19
  Nonce func() []byte
Jordan Sissel's avatar
.  
Jordan Sissel committed
20 21 22 23 24 25 26
}

func NewSession(pk [PUBLICKEYBYTES]byte, sk [SECRETKEYBYTES]byte) (s *Session){
  s = new(Session)
  s.Public = pk
  s.Secret = sk
  s.Precompute()
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
27 28
  s.Nonce = RandomNonceStrategy()
  //s.Nonce = IncrementalNonceStrategy()
Jordan Sissel's avatar
.  
Jordan Sissel committed
29 30 31 32 33 34 35 36 37 38
  return s
}

func (s *Session) Precompute() {
  C.crypto_box_curve25519xsalsa20poly1305_ref_beforenm(
    (*C.uchar)(unsafe.Pointer(&s.k[0])),
    (*C.uchar)(unsafe.Pointer(&s.Public[0])),
    (*C.uchar)(unsafe.Pointer(&s.Secret[0])))
}

39
func (s *Session) Box(plaintext []byte) (ciphertext []byte, nonce []byte) {
Jordan Sissel's avatar
.  
Jordan Sissel committed
40 41
  // XXX: ciphertext needs to be zero-padded at the start for crypto_box_ZEROBYTES
  // ZEROBYTES + len(plaintext) is ciphertext length
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
42
  ciphertext = make([]byte, crypto_box_ZEROBYTES + len(plaintext))
Jordan Sissel's avatar
Jordan Sissel committed
43
  nonce = s.Nonce()
44
  
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
45 46
  m := make([]byte, crypto_box_ZEROBYTES + len(plaintext))
  copy(m[crypto_box_ZEROBYTES:], plaintext)
Jordan Sissel's avatar
.  
Jordan Sissel committed
47 48 49

  C.crypto_box_curve25519xsalsa20poly1305_ref_afternm(
    (*C.uchar)(unsafe.Pointer(&ciphertext[0])),
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
50
    (*C.uchar)(unsafe.Pointer(&m[0])), (C.ulonglong)(len(m)),
Jordan Sissel's avatar
.  
Jordan Sissel committed
51 52 53
    (*C.uchar)(unsafe.Pointer(&nonce[0])),
    (*C.uchar)(unsafe.Pointer(&s.k[0])))

54 55
  //fmt.Printf("ciphertext: %v\n", ciphertext)
  //fmt.Printf("ciphertext2: %v\n", ciphertext[crypto_box_BOXZEROBYTES:])
56
  return ciphertext[crypto_box_BOXZEROBYTES:], nonce[:]
Jordan Sissel's avatar
.  
Jordan Sissel committed
57 58
}

59
func (s *Session) Open(nonce []byte, ciphertext []byte) ([]byte) {
Jordan Sissel's avatar
- tests  
Jordan Sissel committed
60
  // This function assumes the verbatim []byte given by Session.Box() is passed
61 62 63
  m := make([]byte, crypto_box_BOXZEROBYTES + len(ciphertext))
  copy(m[crypto_box_BOXZEROBYTES:], ciphertext)
  plaintext := make([]byte, len(m))
64 65 66 67
  if len(nonce) != crypto_box_NONCEBYTES {
    panic(fmt.Sprintf("Invalid nonce length (%d). Expected %d\n",
                      len(nonce), crypto_box_NONCEBYTES))
  }
Jordan Sissel's avatar
.  
Jordan Sissel committed
68 69 70

  C.crypto_box_curve25519xsalsa20poly1305_ref_open_afternm(
    (*C.uchar)(unsafe.Pointer(&plaintext[0])),
71
    (*C.uchar)(unsafe.Pointer(&m[0])), (C.ulonglong)(len(m)),
Jordan Sissel's avatar
.  
Jordan Sissel committed
72 73 74
    (*C.uchar)(unsafe.Pointer(&nonce[0])),
    (*C.uchar)(unsafe.Pointer(&s.k[0])))

75
  return plaintext[crypto_box_ZEROBYTES:]
Jordan Sissel's avatar
.  
Jordan Sissel committed
76
}