Skip to content

Commit e9a9c20

Browse files
techknowlogickdelvh6543
authored
Create pub/priv keypair for federation (#17071)
* add logic for creating pub/priv keypair for federation * Apply suggestions from code review Co-authored-by: delvh <[email protected]> * make fmt * Update modules/activitypub/keypair.go Co-authored-by: delvh <[email protected]> * add tests * fix revert * more tests * Apply suggestions from code review Co-authored-by: delvh <[email protected]> * make fmt Co-authored-by: delvh <[email protected]> Co-authored-by: 6543 <[email protected]>
1 parent 37b2931 commit e9a9c20

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

modules/activitypub/keypair.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package activitypub
6+
7+
import (
8+
"crypto/rand"
9+
"crypto/rsa"
10+
"crypto/x509"
11+
"encoding/pem"
12+
)
13+
14+
const rsaBits = 2048
15+
16+
// GenerateKeyPair generates a public and private keypair for signing actions by users for activitypub purposes
17+
func GenerateKeyPair() (string, string, error) {
18+
priv, _ := rsa.GenerateKey(rand.Reader, rsaBits)
19+
privPem, err := pemBlockForPriv(priv)
20+
if err != nil {
21+
return "", "", err
22+
}
23+
pubPem, err := pemBlockForPub(&priv.PublicKey)
24+
if err != nil {
25+
return "", "", err
26+
}
27+
return privPem, pubPem, nil
28+
}
29+
30+
func pemBlockForPriv(priv *rsa.PrivateKey) (string, error) {
31+
privBytes := pem.EncodeToMemory(&pem.Block{
32+
Type: "RSA PRIVATE KEY",
33+
Bytes: x509.MarshalPKCS1PrivateKey(priv),
34+
})
35+
return string(privBytes), nil
36+
}
37+
38+
func pemBlockForPub(pub *rsa.PublicKey) (string, error) {
39+
pubASN1, err := x509.MarshalPKIXPublicKey(pub)
40+
if err != nil {
41+
return "", err
42+
}
43+
pubBytes := pem.EncodeToMemory(&pem.Block{
44+
Type: "PUBLIC KEY",
45+
Bytes: pubASN1,
46+
})
47+
return string(pubBytes), nil
48+
}

modules/activitypub/keypair_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package activitypub
6+
7+
import (
8+
"crypto"
9+
"crypto/rand"
10+
"crypto/rsa"
11+
"crypto/sha256"
12+
"crypto/x509"
13+
"encoding/pem"
14+
"regexp"
15+
"testing"
16+
17+
"github.com/stretchr/testify/assert"
18+
)
19+
20+
func TestKeygen(t *testing.T) {
21+
priv, pub, err := GenerateKeyPair()
22+
assert.NoError(t, err)
23+
24+
assert.NotEmpty(t, priv)
25+
assert.NotEmpty(t, pub)
26+
27+
assert.Regexp(t, regexp.MustCompile("^-----BEGIN RSA PRIVATE KEY-----.*"), priv)
28+
assert.Regexp(t, regexp.MustCompile("^-----BEGIN PUBLIC KEY-----.*"), pub)
29+
30+
}
31+
32+
func TestSignUsingKeys(t *testing.T) {
33+
priv, pub, err := GenerateKeyPair()
34+
assert.NoError(t, err)
35+
36+
privPem, _ := pem.Decode([]byte(priv))
37+
if privPem == nil || privPem.Type != "RSA PRIVATE KEY" {
38+
t.Fatal("key is wrong type")
39+
}
40+
41+
privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes)
42+
assert.NoError(t, err)
43+
44+
pubPem, _ := pem.Decode([]byte(pub))
45+
if pubPem == nil || pubPem.Type != "PUBLIC KEY" {
46+
t.Fatal("key failed to decode")
47+
}
48+
49+
pubParsed, err := x509.ParsePKIXPublicKey(pubPem.Bytes)
50+
assert.NoError(t, err)
51+
52+
// Sign
53+
msg := "activity pub is great!"
54+
h := sha256.New()
55+
h.Write([]byte(msg))
56+
d := h.Sum(nil)
57+
sig, err := rsa.SignPKCS1v15(rand.Reader, privParsed, crypto.SHA256, d)
58+
assert.NoError(t, err)
59+
60+
// Verify
61+
err = rsa.VerifyPKCS1v15(pubParsed.(*rsa.PublicKey), crypto.SHA256, d, sig)
62+
assert.NoError(t, err)
63+
}

0 commit comments

Comments
 (0)