From ae3b826bf3a40003a209a33658141f125eadfcdb Mon Sep 17 00:00:00 2001 From: Matti R Date: Thu, 16 Sep 2021 17:37:37 -0400 Subject: [PATCH 1/9] add logic for creating pub/priv keypair for federation --- modules/activitypub/keypair.go | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 modules/activitypub/keypair.go diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go new file mode 100644 index 000000000000..4d6901a4f1d6 --- /dev/null +++ b/modules/activitypub/keypair.go @@ -0,0 +1,57 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package activitypub + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" +) + +const rsaBits = 2048 + +// GenerateKeyPair generates a public and private keypair for signing actions by users for activitypub purposes +func GenerateKeyPair() (string, string, error) { + priv, _ := rsa.GenerateKey(rand.Reader, rsaBits) + privPem, err := pemBlockForPriv(priv) + if err != nil { + return "", "", err + } + pubPem, err := pemBlockForPub(publicKey(priv)) + if err != nil { + return "", "", err + } + return privPem, pubPem, nil +} + +func pemBlockForPriv(priv *rsa.PrivateKey) (string, error) { + privBytes := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(priv), + }) + return string(privBytes), nil +} + +func pemBlockForPub(pub interface{}) (string, error) { + pubASN1, err := x509.MarshalPKIXPublicKey(pub) + if err != nil { + return "", err + } + pubBytes := pem.EncodeToMemory(&pem.Block{ + Type: "PUBLIC KEY", + Bytes: pubASN1, + }) + return string(pubBytes), nil +} + +func publicKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + default: + return nil + } +} From 1440be4450c4f7779b3421290d6084a79feef03e Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Thu, 16 Sep 2021 19:32:38 -0400 Subject: [PATCH 2/9] Apply suggestions from code review Co-authored-by: delvh --- modules/activitypub/keypair.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go index 4d6901a4f1d6..d90aed7cb59c 100644 --- a/modules/activitypub/keypair.go +++ b/modules/activitypub/keypair.go @@ -20,7 +20,7 @@ func GenerateKeyPair() (string, string, error) { if err != nil { return "", "", err } - pubPem, err := pemBlockForPub(publicKey(priv)) + pubPem, err := pemBlockForPub(&priv.PublicKey) if err != nil { return "", "", err } @@ -47,11 +47,3 @@ func pemBlockForPub(pub interface{}) (string, error) { return string(pubBytes), nil } -func publicKey(priv interface{}) interface{} { - switch k := priv.(type) { - case *rsa.PrivateKey: - return &k.PublicKey - default: - return nil - } -} From 3be4b805d6955cb4c698907bcd439f4bc7930b84 Mon Sep 17 00:00:00 2001 From: Matti R Date: Thu, 16 Sep 2021 19:34:13 -0400 Subject: [PATCH 3/9] make fmt --- modules/activitypub/keypair.go | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go index d90aed7cb59c..71bdeb5fd090 100644 --- a/modules/activitypub/keypair.go +++ b/modules/activitypub/keypair.go @@ -46,4 +46,3 @@ func pemBlockForPub(pub interface{}) (string, error) { }) return string(pubBytes), nil } - From 3bcd812f3803f368b02e81bb65b2c814d283b658 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Sat, 18 Sep 2021 21:11:10 -0400 Subject: [PATCH 4/9] Update modules/activitypub/keypair.go Co-authored-by: delvh --- modules/activitypub/keypair.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go index 71bdeb5fd090..ab540ee22545 100644 --- a/modules/activitypub/keypair.go +++ b/modules/activitypub/keypair.go @@ -35,7 +35,7 @@ func pemBlockForPriv(priv *rsa.PrivateKey) (string, error) { return string(privBytes), nil } -func pemBlockForPub(pub interface{}) (string, error) { +func pemBlockForPub(pub rsa.PublicKey) (string, error) { pubASN1, err := x509.MarshalPKIXPublicKey(pub) if err != nil { return "", err From 9095e4e4a6039d230e53f23174ca760dafca3fcd Mon Sep 17 00:00:00 2001 From: Matti R Date: Sun, 19 Sep 2021 22:49:53 -0400 Subject: [PATCH 5/9] add tests --- modules/activitypub/keypair.go | 2 +- modules/activitypub/keypair_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 modules/activitypub/keypair_test.go diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go index ab540ee22545..71bdeb5fd090 100644 --- a/modules/activitypub/keypair.go +++ b/modules/activitypub/keypair.go @@ -35,7 +35,7 @@ func pemBlockForPriv(priv *rsa.PrivateKey) (string, error) { return string(privBytes), nil } -func pemBlockForPub(pub rsa.PublicKey) (string, error) { +func pemBlockForPub(pub interface{}) (string, error) { pubASN1, err := x509.MarshalPKIXPublicKey(pub) if err != nil { return "", err diff --git a/modules/activitypub/keypair_test.go b/modules/activitypub/keypair_test.go new file mode 100644 index 000000000000..699fad0d5aac --- /dev/null +++ b/modules/activitypub/keypair_test.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package activitypub + +import ( + "regexp" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestKeygen(t *testing.T) { + priv, pub, err := GenerateKeyPair() + + assert.NoError(t, err) + + assert.NotEmpty(t, priv) + assert.NotEmpty(t, pub) + + assert.Regexp(t, regexp.MustCompile("^-----BEGIN RSA PRIVATE KEY-----.*"), priv) + assert.Regexp(t, regexp.MustCompile("^-----BEGIN PUBLIC KEY-----.*"), pub) + +} From d6b3e9637955c14f5b7372a1f1d9fbd49fe5a9a8 Mon Sep 17 00:00:00 2001 From: Matti R Date: Sun, 19 Sep 2021 22:52:03 -0400 Subject: [PATCH 6/9] fix revert --- modules/activitypub/keypair.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/activitypub/keypair.go b/modules/activitypub/keypair.go index 71bdeb5fd090..fe6aba9058ae 100644 --- a/modules/activitypub/keypair.go +++ b/modules/activitypub/keypair.go @@ -35,7 +35,7 @@ func pemBlockForPriv(priv *rsa.PrivateKey) (string, error) { return string(privBytes), nil } -func pemBlockForPub(pub interface{}) (string, error) { +func pemBlockForPub(pub *rsa.PublicKey) (string, error) { pubASN1, err := x509.MarshalPKIXPublicKey(pub) if err != nil { return "", err From 09b332d2e1a367ae8066441e6344160eccbec966 Mon Sep 17 00:00:00 2001 From: Matti R Date: Mon, 27 Sep 2021 15:37:37 -0400 Subject: [PATCH 7/9] more tests --- modules/activitypub/keypair_test.go | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/modules/activitypub/keypair_test.go b/modules/activitypub/keypair_test.go index 699fad0d5aac..473f27244146 100644 --- a/modules/activitypub/keypair_test.go +++ b/modules/activitypub/keypair_test.go @@ -7,13 +7,18 @@ package activitypub import ( "regexp" "testing" + "encoding/pem" + "crypto/x509" + "crypto" + "crypto/sha256" + "crypto/rsa" + "crypto/rand" "github.com/stretchr/testify/assert" ) func TestKeygen(t *testing.T) { priv, pub, err := GenerateKeyPair() - assert.NoError(t, err) assert.NotEmpty(t, priv) @@ -23,3 +28,40 @@ func TestKeygen(t *testing.T) { assert.Regexp(t, regexp.MustCompile("^-----BEGIN PUBLIC KEY-----.*"), pub) } + +func TestSignUsingKeys(t *testing.T) { + priv, pub, err := GenerateKeyPair() + assert.NoError(t, err) + + privPem, _ := pem.Decode([]byte(priv)) + if privPem == nil || privPem.Type != "RSA PRIVATE KEY" { + t.Fatal("key is wrong type") + } + + privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes) + if err != nil { + assert.NoError(t, err) + } + + pubPem, _ := pem.Decode([]byte(pub)) + if pubPem == nil || pubPem.Type != "PUBLIC KEY" { + t.Fatal("key failed to decode") + } + + pubParsed, err := x509.ParsePKIXPublicKey(pubPem.Bytes) + if err != nil { + assert.NoError(t, err) + } + + // Sign + msg := "activity pub is great!" + h := sha256.New() + h.Write([]byte(msg)) + d := h.Sum(nil) + sig, err := rsa.SignPKCS1v15(rand.Reader, privParsed, crypto.SHA256, d) + assert.NoError(t, err) + + // Verify + err = rsa.VerifyPKCS1v15(pubParsed.(*rsa.PublicKey), crypto.SHA256, d, sig) + assert.NoError(t, err) +} \ No newline at end of file From e4e4aeb72c8a51b6c498c0108cfe854e3b36a033 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Mon, 27 Sep 2021 16:33:21 -0400 Subject: [PATCH 8/9] Apply suggestions from code review Co-authored-by: delvh --- modules/activitypub/keypair_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/activitypub/keypair_test.go b/modules/activitypub/keypair_test.go index 473f27244146..55261b5f7971 100644 --- a/modules/activitypub/keypair_test.go +++ b/modules/activitypub/keypair_test.go @@ -39,9 +39,7 @@ func TestSignUsingKeys(t *testing.T) { } privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes) - if err != nil { - assert.NoError(t, err) - } + assert.NoError(t, err) pubPem, _ := pem.Decode([]byte(pub)) if pubPem == nil || pubPem.Type != "PUBLIC KEY" { @@ -49,9 +47,7 @@ func TestSignUsingKeys(t *testing.T) { } pubParsed, err := x509.ParsePKIXPublicKey(pubPem.Bytes) - if err != nil { - assert.NoError(t, err) - } + assert.NoError(t, err) // Sign msg := "activity pub is great!" From 0303e4bcc22a3a8382735a6bcbd0afe03f4545c2 Mon Sep 17 00:00:00 2001 From: Matti R Date: Mon, 27 Sep 2021 16:37:14 -0400 Subject: [PATCH 9/9] make fmt --- modules/activitypub/keypair_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/activitypub/keypair_test.go b/modules/activitypub/keypair_test.go index 55261b5f7971..5d876937b142 100644 --- a/modules/activitypub/keypair_test.go +++ b/modules/activitypub/keypair_test.go @@ -5,14 +5,14 @@ package activitypub import ( - "regexp" - "testing" - "encoding/pem" - "crypto/x509" "crypto" - "crypto/sha256" - "crypto/rsa" "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/pem" + "regexp" + "testing" "github.com/stretchr/testify/assert" ) @@ -60,4 +60,4 @@ func TestSignUsingKeys(t *testing.T) { // Verify err = rsa.VerifyPKCS1v15(pubParsed.(*rsa.PublicKey), crypto.SHA256, d, sig) assert.NoError(t, err) -} \ No newline at end of file +}