Merge "x/lib/ibe: Marshaling/Unmarshaling functions."
diff --git a/ibe/.api b/ibe/.api
index dcdc2f2..7bbaf0c 100644
--- a/ibe/.api
+++ b/ibe/.api
@@ -1,4 +1,8 @@
+pkg ibe, func MarshalParams(Params) ([]byte, error)
+pkg ibe, func MarshalPrivateKey(PrivateKey) ([]byte, error)
 pkg ibe, func SetupBB1() (Master, error)
+pkg ibe, func UnmarshalParams([]byte) (Params, error)
+pkg ibe, func UnmarshalPrivateKey(Params, []byte) (PrivateKey, error)
 pkg ibe, type Ciphertext [160]byte
 pkg ibe, type Master interface { Extract, Params }
 pkg ibe, type Master interface, Extract(string) (PrivateKey, error)
diff --git a/ibe/bb1.go b/ibe/bb1.go
index 782f163..71e6937 100644
--- a/ibe/bb1.go
+++ b/ibe/bb1.go
@@ -23,7 +23,11 @@
 
 var errBadCiphertext = errors.New("invalid ciphertext")
 
-const marshaledG1Size = 64
+const (
+	marshaledG1Size = 2 * 32
+	marshaledG2Size = 4 * 32
+	marshaledGTSize = 12 * 32
+)
 
 // Setup creates an ibe.Master based on the BB1 scheme described in "Efficient
 // Selective Identity-Based Encryption Without Random Oracles" by Dan Boneh and
diff --git a/ibe/bb1_test.go b/ibe/bb1_test.go
index cbd5854..8a8f4e8 100644
--- a/ibe/bb1_test.go
+++ b/ibe/bb1_test.go
@@ -80,6 +80,72 @@
 	bb1C       Ciphertext
 )
 
+func TestBB1Marshaling(t *testing.T) {
+	bb1P := bb1.Params()
+	pbytes, err := MarshalParams(bb1P)
+	if err != nil {
+		t.Fatal(err)
+	}
+	skbytes, err := MarshalPrivateKey(bb1SK)
+	if err != nil {
+		t.Fatal(err)
+	}
+	var m Plaintext
+	if n := copy(m[:], []byte("01234567899876543210123456789012")); n != len(m) {
+		t.Fatalf("%v vs. %v", n, len(m))
+	}
+	var C1, C2 Ciphertext
+	var m1, m2 Plaintext
+	// Encrypt with the original params, decrypt with the unmarshaled key.
+	if err := bb1P.Encrypt("alice", &m, &C1); err != nil {
+		t.Error(err)
+	} else if sk, err := UnmarshalPrivateKey(bb1P, skbytes); err != nil {
+		t.Error(err)
+	} else if err := sk.Decrypt(&C1, &m2); err != nil {
+		t.Error(err)
+	} else if !bytes.Equal(m[:], m2[:]) {
+		t.Errorf("Got %q, want %q", m, m2)
+	}
+	// Encrypt with the unmarshaled params, decrypt with the original key.
+	if p, err := UnmarshalParams(pbytes); err != nil {
+		t.Error(err)
+	} else if err := p.Encrypt("alice", &m, &C2); err != nil {
+		t.Error(err)
+	} else if err := bb1SK.Decrypt(&C2, &m1); err != nil {
+		t.Error(err)
+	} else if !bytes.Equal(m[:], m1[:]) {
+		t.Errorf("Got %q, want %q", m, m1)
+	}
+
+	// Truncation errors
+	if _, err := UnmarshalParams(pbytes[:len(pbytes)-1]); err == nil {
+		t.Errorf("UnmarshalParams succeeded on truncated input")
+	}
+	if _, err := UnmarshalPrivateKey(bb1P, skbytes[:len(skbytes)-1]); err == nil {
+		t.Errorf("UnmarshalPrivateKey succeeded on truncated input")
+	}
+	// Extension errors
+	if _, err := UnmarshalParams(append(pbytes, 0)); err == nil {
+		t.Errorf("UnmarshalParams succeeded on extended input")
+	}
+	if _, err := UnmarshalPrivateKey(bb1P, append(skbytes, 0)); err == nil {
+		t.Errorf("UnmarshalPrivateKey succeeded on extended input")
+	}
+	// Zero length (no valid header either)
+	if _, err := UnmarshalParams(nil); err == nil {
+		t.Errorf("UnmarshalParams succeeded on nil input")
+	}
+	if _, err := UnmarshalParams([]byte{}); err == nil {
+		t.Errorf("UnmarshalParams succeeded on zero length input")
+	}
+	if _, err := UnmarshalPrivateKey(bb1P, nil); err == nil {
+		t.Errorf("UnmarshalPrivateKey succeeded on nil input")
+	}
+	if _, err := UnmarshalPrivateKey(bb1P, []byte{}); err == nil {
+		t.Errorf("UnmarshalPrivateKey succeeded on zero length input")
+	}
+}
+
 func init() {
 	var err error
 	if bb1, err = SetupBB1(); err != nil {
diff --git a/ibe/marshal.go b/ibe/marshal.go
new file mode 100644
index 0000000..ca6bae4
--- /dev/null
+++ b/ibe/marshal.go
@@ -0,0 +1,165 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ibe
+
+import (
+	"bytes"
+	"fmt"
+	"math/big"
+
+	"golang.org/x/crypto/bn256"
+)
+
+var magicNumber = []byte{0x1b, 0xe0} // prefix that appears in the marshaled form: 2 bytes
+
+type marshaledType byte
+
+const (
+	// types of encoded bytes, 1 byte
+	typeBB1Params     marshaledType = 0
+	typeBB1PrivateKey               = 1
+
+	// Sizes excluding the magic number and type header.
+	headerSize                 = 3
+	marshaledBB1ParamsSize     = 2*marshaledG1Size + 2*marshaledG2Size + marshaledGTSize
+	marshaledBB1PrivateKeySize = 2 * marshaledG2Size
+)
+
+func writeHeader(typ marshaledType) []byte {
+	ret := make([]byte, headerSize)
+	copy(ret, magicNumber)
+	ret[len(magicNumber)] = byte(typ)
+	return ret
+}
+
+// readHeader parses hdr and returns the message type and the remainder of the
+// message, excluding the header.
+func readHeader(hdr []byte) (marshaledType, []byte, error) {
+	if len(hdr) < headerSize {
+		return 0, nil, fmt.Errorf("header is too small")
+	}
+	if !bytes.Equal(hdr[0:len(magicNumber)], magicNumber) {
+		return 0, nil, fmt.Errorf("invalid magic number")
+	}
+	return marshaledType(hdr[len(magicNumber)]), hdr[headerSize:], nil
+}
+
+// MarshalParams encodes p into a byte slice.
+func MarshalParams(p Params) ([]byte, error) {
+	switch p := p.(type) {
+	case *bb1params:
+		ret := make([]byte, 0, headerSize+marshaledBB1ParamsSize)
+		// g and gHat are the generators, do not need to be marshaled.
+		for _, field := range [][]byte{
+			writeHeader(typeBB1Params),
+			p.g1.Marshal(),
+			p.h.Marshal(),
+			p.g1Hat.Marshal(),
+			p.hHat.Marshal(),
+			p.v.Marshal(),
+		} {
+			ret = append(ret, field...)
+		}
+		return ret, nil
+	default:
+		return nil, fmt.Errorf("MarshalParams for %T for implemented yet", p)
+	}
+}
+
+// UnmarshalParams parses an encoded Params object.
+func UnmarshalParams(data []byte) (Params, error) {
+	var typ marshaledType
+	var err error
+	if typ, data, err = readHeader(data); err != nil {
+		return nil, err
+	}
+	advance := func(n int) []byte {
+		ret := data[0:n]
+		data = data[n:]
+		return ret
+	}
+	switch typ {
+	case typeBB1Params:
+		if len(data) != marshaledBB1ParamsSize {
+			return nil, fmt.Errorf("invalid size")
+		}
+		p := &bb1params{v: new(bn256.GT)}
+		one := big.NewInt(1)
+		p.g.ScalarBaseMult(one)
+		p.gHat.ScalarBaseMult(one)
+		if _, ok := p.g1.Unmarshal(advance(marshaledG1Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal g1")
+		}
+		if _, ok := p.h.Unmarshal(advance(marshaledG1Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal h")
+		}
+		if _, ok := p.g1Hat.Unmarshal(advance(marshaledG2Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal g1Hat")
+		}
+		if _, ok := p.hHat.Unmarshal(advance(marshaledG2Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal hHat")
+		}
+		if _, ok := p.v.Unmarshal(advance(marshaledGTSize)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal v")
+		}
+		return p, nil
+	default:
+		return nil, fmt.Errorf("unrecognized Params type (%d)", typ)
+	}
+}
+
+// MarshalPrivateKey encodes the private component of k into a byte slice.
+func MarshalPrivateKey(k PrivateKey) ([]byte, error) {
+	switch k := k.(type) {
+	case *bb1PrivateKey:
+		ret := make([]byte, 0, headerSize+marshaledBB1PrivateKeySize)
+		for _, field := range [][]byte{
+			writeHeader(typeBB1PrivateKey),
+			k.d0.Marshal(),
+			k.d1.Marshal(),
+		} {
+			ret = append(ret, field...)
+		}
+		return ret, nil
+	default:
+		return nil, fmt.Errorf("MarshalPrivateKey for %T for implemented yet", k)
+	}
+}
+
+// UnmarshalPrivateKey parses an encoded PrivateKey object.
+func UnmarshalPrivateKey(params Params, data []byte) (PrivateKey, error) {
+	var typ marshaledType
+	var err error
+	if typ, data, err = readHeader(data); err != nil {
+		return nil, err
+	}
+	advance := func(n int) []byte {
+		ret := data[0:n]
+		data = data[n:]
+		return ret
+	}
+	switch typ {
+	case typeBB1PrivateKey:
+		if len(data) != marshaledBB1PrivateKeySize {
+			return nil, fmt.Errorf("invalid size")
+		}
+		k := new(bb1PrivateKey)
+		if _, ok := k.d0.Unmarshal(advance(marshaledG2Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal d0")
+		}
+		if _, ok := k.d1.Unmarshal(advance(marshaledG2Size)); !ok {
+			return nil, fmt.Errorf("failed to unmarshal d1")
+		}
+		if p, ok := params.(*bb1params); !ok {
+			return nil, fmt.Errorf("params type %T incompatible with %T", params, k)
+		} else {
+			k.params = new(bb1params)
+			*(k.params) = *p
+		}
+		return k, nil
+	default:
+		return nil, fmt.Errorf("unrecognized private key type (%d)", typ)
+	}
+}