Skip to content

Commit

Permalink
+docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ConradIrwin committed Apr 27, 2014
1 parent f1b773d commit ebfb9da
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 24 deletions.
21 changes: 10 additions & 11 deletions partial_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strings"
)

// A PartialKey is a triple (E, N, D) where E is the public exponent,
// N is the modulus, and D is a part of the mRSA private key.
type PartialKey mrsa.PrivateKey

const (
Expand All @@ -27,6 +29,8 @@ var (
ErrPartialKeyWrongExponent = errors.New("octokey/partial_key: invalid exponent")
)

// GeneratePartialKey generates two new PartialKeys that can be used
// together to perform mRSA operations.
func GeneratePartialKey() (*PartialKey, *PartialKey, error) {

k, err := rsa.GenerateKey(rand.Reader, BIT_LENGTH)
Expand All @@ -44,6 +48,7 @@ func GeneratePartialKey() (*PartialKey, *PartialKey, error) {
return (*PartialKey)(d1), (*PartialKey)(d2), nil
}

// NewPartialKey reads a PartialKey from its string representation
func NewPartialKey(text string) (*PartialKey, error) {

text = strings.TrimSpace(text)
Expand Down Expand Up @@ -98,11 +103,8 @@ func NewPartialKey(text string) (*PartialKey, error) {
return k, nil
}

// Sign runs partial mRSA decryption on a number. You will need to finalize the
// PartialDecrypt runs partial mRSA decryption on a number. You will need to finalize the
// signature once you have run Sign with all parts of the key.
func (k *PartialKey) Sign(m *big.Int) (*big.Int, error) {
return k.PartialDecrypt(m)
}
func (k *PartialKey) PartialDecrypt(c *big.Int) (*big.Int, error) {
mrsaKey := mrsa.PrivateKey(*k)
return mrsaKey.PartialDecrypt(c)
Expand All @@ -111,7 +113,8 @@ func (k *PartialKey) PartialDecrypt(c *big.Int) (*big.Int, error) {
// Format gives you the partial key in the canonical representation including
// ----BEGIN/END headers.
func (k *PartialKey) String() string {
b := k.Buffer()
b := new(buffer.Buffer)
k.WriteBuffer(b)
if b.Error != nil {
panic(errors.New("invalid partial key: " + b.Error.Error()))
}
Expand Down Expand Up @@ -142,14 +145,10 @@ func lineWrap(s string, w int) string {

return string(b.Bytes())
}

func (k *PartialKey) Buffer() *buffer.Buffer {
b := new(buffer.Buffer)

// WriteBuffer writes the PartialKey to a buffer
func (k *PartialKey) WriteBuffer(b *buffer.Buffer) {
b.AddString(KEY_TYPE)
b.AddMPInt(big.NewInt(int64(k.E)))
b.AddMPInt(k.N)
b.AddMPInt(k.D)

return b
}
11 changes: 8 additions & 3 deletions partial_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@ import (
"reflect"
"strings"
)

// A PartialSigner uses an escrow server to partially sign an mRSA request.
// Internally it sends a SignRequest to the server and expects a SignRequest
// response (which it could forward on to further servers if necessary)
type PartialSigner struct {
Url string
Key *PublicKey
}

// PartialDecrypt is used by the mrsa.Session to actually perform decryption.
func (ps *PartialSigner) PartialDecrypt(c *big.Int) (*big.Int, error) {

request := new(SignRequest)
request.Key = ps.Key
request.M = c

resp, err := ps.MakeRequest(request.String())
resp, err := ps.makeRequest(request.String())

if err != nil {
return nil, err
Expand All @@ -39,7 +42,9 @@ func (ps *PartialSigner) PartialDecrypt(c *big.Int) (*big.Int, error) {
return response.M, nil
}

func (ps *PartialSigner) MakeRequest(str string) (string, error) {
// makeRequest sends a sign reqquest to the mRSA escrow server and returns
// the resulting sign request
func (ps *PartialSigner) makeRequest(str string) (string, error) {

res, err := http.Post(ps.Url, "octokey/sign-request", strings.NewReader(str))
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions public_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"strings"
)

// A PublicKey is a pair of E (the public exponent) and N (the modulus)
// of an mRSA keypair.
type PublicKey mrsa.PublicKey

const PUBLIC_KEY_TYPE = "ssh-rsa"
Expand All @@ -17,6 +19,7 @@ var (
ErrPublicKeyFormat = errors.New("octokey/public_key: invalid input")
)

// NewPublicKey reads the public key from a string.
func NewPublicKey(text string) (*PublicKey, error) {

text = strings.TrimSpace(text)
Expand Down Expand Up @@ -44,12 +47,14 @@ func NewPublicKey(text string) (*PublicKey, error) {
return k, nil
}

// WriteBuffer writes the public key to a buffer.
func (p *PublicKey) WriteBuffer(b *buffer.Buffer) {
b.AddString(PUBLIC_KEY_TYPE)
b.AddMPInt(big.NewInt(int64(p.E)))
b.AddMPInt(p.N)
}

// ReadBuffer reads the public key from a buffer.
func (p *PublicKey) ReadBuffer(b *buffer.Buffer) error {

t := b.ScanString()
Expand All @@ -70,6 +75,7 @@ func (p *PublicKey) ReadBuffer(b *buffer.Buffer) error {
return nil
}

// String returns the public key in the same format as used by ssh
func (p *PublicKey) String() string {
b := new(buffer.Buffer)

Expand Down
43 changes: 33 additions & 10 deletions sign_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"strings"
)

// A SignRequest represents a request to perform a partial mRSA sign, and also
// the result of that computation. It is represented as a Buffer of
// ("ssh-rsa" // || E || N || M) where E is the public exponent (MPint 65537)
// N is the modulus (a 2048 bit MPint), and M is the message (a 2048 bit MPInt
// strictly less than N)
type SignRequest struct {
Key *PublicKey
M *big.Int
Expand All @@ -21,6 +26,7 @@ var (
ErrSignRequestFormat = errors.New("escrow/signing_request: invalid format")
)

// NewSignRequest reads a sign request from a string.
func NewSignRequest(text string) (*SignRequest, error) {

text = strings.TrimSpace(text)
Expand All @@ -42,31 +48,46 @@ func NewSignRequest(text string) (*SignRequest, error) {

base64 := split[len(split)-1]

buff := buffer.NewBuffer(base64)
b := buffer.NewBuffer(base64)
request := new(SignRequest)
err := request.ReadBuffer(b)
if err != nil {
return nil, err
}
b.ScanEof()

if b.Error != nil {
return nil, b.Error
}

return request, nil
}

// ReadBuffer reads a SignRequest from a buffer.
func (request *SignRequest) ReadBuffer(b *buffer.Buffer) error {

publicKey := new(PublicKey)
err := publicKey.ReadBuffer(buff)
err := publicKey.ReadBuffer(b)
if err != nil {
return nil, err
return err
}

msg := buff.ScanMPInt()
buff.ScanEof()
msg := b.ScanMPInt()

if buff.Error != nil {
return nil, buff.Error
if msg.Cmp(publicKey.N) >= 0 {
return errors.New("cannot sign message > N")
}

request := new(SignRequest)
request.Key = publicKey
request.M = msg

return request, nil
return nil
}

// Sign partially signs the request with the given key.
func (request *SignRequest) Sign(key *PartialKey) error {

m, err := key.Sign(request.M)
m, err := key.PartialDecrypt(request.M)

if err != nil {
return err
Expand All @@ -77,6 +98,8 @@ func (request *SignRequest) Sign(key *PartialKey) error {
return nil
}

// String produces the line-wrapped base-64 version of the challenge,
// suitable for being passed to NewSignRequest()
func (request *SignRequest) String() string {
b := new(buffer.Buffer)

Expand Down

0 comments on commit ebfb9da

Please sign in to comment.