very rough su3 creation and signing
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
/i2p-reseeder
|
||||
/cert.pem
|
||||
/key.pem
|
||||
/netdb
|
||||
i2pseeds.su3
|
||||
/_netdb
|
||||
i2pseeds.su3
|
||||
reseed_cert.pem
|
||||
reseed_private.pem
|
||||
|
||||
88
cmd/keygen.go
Normal file
88
cmd/keygen.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func NewKeygenCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "keygen",
|
||||
Usage: "Generate keys for reseed Su3 signing",
|
||||
Description: "Generate keys for reseed Su3 signing",
|
||||
Action: keygenAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "signer",
|
||||
Usage: "Your email address (ex. something@mail.i2p)",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func keygenAction(c *cli.Context) {
|
||||
//"CN=" + cname + ",OU=" + ou + ",O=I2P Anonymous Network,L=XX,ST=XX,C=XX",
|
||||
template := &x509.Certificate{
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
SubjectKeyId: []byte{1, 2, 3},
|
||||
SerialNumber: big.NewInt(1234),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"I2P Anonymous Network"},
|
||||
OrganizationalUnit: []string{"I2P"},
|
||||
Locality: []string{"XX"},
|
||||
StreetAddress: []string{"XX"},
|
||||
Country: []string{"XX"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(10, 0, 0),
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
}
|
||||
|
||||
// generate private key
|
||||
privatekey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
publickey := &privatekey.PublicKey
|
||||
|
||||
// create a self-signed certificate. template = parent
|
||||
var parent = template
|
||||
cert, err := x509.CreateCertificate(rand.Reader, template, parent, publickey, privatekey)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// save private key
|
||||
pemfile, err := os.Create("reseed_private.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open reseed_cert.pem for writing: %s", err)
|
||||
}
|
||||
var pemkey = &pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(privatekey)}
|
||||
pem.Encode(pemfile, pemkey)
|
||||
pemfile.Close()
|
||||
fmt.Println("private key saved to reseed_private.pem")
|
||||
|
||||
// save cert
|
||||
certOut, err := os.Create("reseed_cert.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open reseed_cert.pem for writing: %s", err)
|
||||
}
|
||||
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
|
||||
certOut.Close()
|
||||
fmt.Println("certificate saved to reseed_cert.pem")
|
||||
}
|
||||
@@ -1,18 +1,20 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
// "github.com/MDrollette/go-i2p/reseed"
|
||||
"github.com/MDrollette/go-i2p/reseed"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func NewReseederCommand() cli.Command {
|
||||
func NewReseedCommand() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "reseeder",
|
||||
Name: "reseed",
|
||||
Usage: "Start a reseed server",
|
||||
Description: "Start a reseed server",
|
||||
Action: reseederAction,
|
||||
Action: reseedAction,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "addr",
|
||||
@@ -23,6 +25,24 @@ func NewReseederCommand() cli.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func reseederAction(c *cli.Context) {
|
||||
func reseedAction(c *cli.Context) {
|
||||
log.Println("Starting server on", c.String("addr"))
|
||||
|
||||
netdb := reseed.NewLocalNetDb(c.Args().Get(0))
|
||||
reseeder := reseed.NewReseeder(netdb)
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
peer := reseeder.Peer(r)
|
||||
seeds, err := reseeder.Seed(peer)
|
||||
if nil != err {
|
||||
fmt.Fprintf(w, "Problem: '%s'", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, s := range seeds {
|
||||
fmt.Fprintf(w, "%s\n", s.Name)
|
||||
}
|
||||
})
|
||||
|
||||
http.ListenAndServe("127.0.0.1:9090", nil)
|
||||
}
|
||||
|
||||
60
cmd/su3.go
Normal file
60
cmd/su3.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/MDrollette/go-i2p/reseed"
|
||||
"github.com/MDrollette/go-i2p/su3"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func NewSu3Command() cli.Command {
|
||||
return cli.Command{
|
||||
Name: "su3",
|
||||
Usage: "Do SU3 things",
|
||||
Description: "Do SU3 things",
|
||||
Action: su3Action,
|
||||
Flags: []cli.Flag{},
|
||||
}
|
||||
}
|
||||
|
||||
func su3Action(c *cli.Context) {
|
||||
netdb := reseed.NewLocalNetDb(c.Args().Get(0))
|
||||
reseeder := reseed.NewReseeder(netdb)
|
||||
|
||||
// make a fake request to get a peer
|
||||
r, _ := http.NewRequest("GET", "/i2pseeds.su3", nil)
|
||||
|
||||
peer := reseeder.Peer(r)
|
||||
seeds, err := reseeder.Seed(peer)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
return
|
||||
}
|
||||
|
||||
// load our signing privKey
|
||||
privPem, err := ioutil.ReadFile("reseed_private.pem")
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
return
|
||||
}
|
||||
privDer, _ := pem.Decode(privPem)
|
||||
privKey, err := x509.ParsePKCS1PrivateKey(privDer.Bytes)
|
||||
if nil != err {
|
||||
log.Fatalln(err)
|
||||
return
|
||||
}
|
||||
|
||||
// create an SU3 from the seed
|
||||
su3File, err := reseeder.CreateSu3(seeds)
|
||||
su3File.SetSignerId("matt@drollette.com")
|
||||
// sign the su3 with our key
|
||||
su3File.Sign(privKey, su3.SIGTYPE_RSA_SHA512)
|
||||
|
||||
//write the file to disk
|
||||
ioutil.WriteFile("i2pseeds.su3", su3File.Bytes(), 0777)
|
||||
}
|
||||
@@ -30,11 +30,11 @@ func su3VerifyAction(c *cli.Context) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(su3File.String())
|
||||
|
||||
if err := su3File.VerifySignature(); nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(su3File.String())
|
||||
|
||||
fmt.Println("Verified signature.")
|
||||
}
|
||||
|
||||
4
main.go
4
main.go
@@ -14,8 +14,10 @@ func main() {
|
||||
app.Usage = "I2P commands"
|
||||
app.Flags = []cli.Flag{}
|
||||
app.Commands = []cli.Command{
|
||||
cmd.NewReseederCommand(),
|
||||
cmd.NewReseedCommand(),
|
||||
cmd.NewSu3VerifyCommand(),
|
||||
cmd.NewKeygenCommand(),
|
||||
cmd.NewSu3Command(),
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
|
||||
127
reseed/server.go
127
reseed/server.go
@@ -1 +1,128 @@
|
||||
package reseed
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/MDrollette/go-i2p/su3"
|
||||
)
|
||||
|
||||
type routerInfo struct {
|
||||
Name string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type Peer string
|
||||
type Seed []routerInfo
|
||||
|
||||
type Reseeder interface {
|
||||
// seed a peer with routerinfos
|
||||
Seed(p Peer) (Seed, error)
|
||||
// get a peer from a given request
|
||||
Peer(r *http.Request) Peer
|
||||
// create an Su3 file from the given seeds
|
||||
CreateSu3(seeds Seed) (*su3.Su3File, error)
|
||||
}
|
||||
|
||||
type ReseederImpl struct {
|
||||
netdb NetDbProvider
|
||||
peers map[string]Peer
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
func NewReseeder(netdb NetDbProvider) *ReseederImpl {
|
||||
return &ReseederImpl{
|
||||
netdb: netdb,
|
||||
peers: make(map[string]Peer),
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *ReseederImpl) Seed(p Peer) (Seed, error) {
|
||||
all, err := rs.netdb.RouterInfos()
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return Seed(all), nil
|
||||
}
|
||||
|
||||
func (rs *ReseederImpl) Peer(r *http.Request) Peer {
|
||||
rs.m.Lock()
|
||||
defer rs.m.Unlock()
|
||||
|
||||
if p, ok := rs.peers[r.RemoteAddr]; !ok {
|
||||
rs.peers[r.RemoteAddr] = Peer(r.RemoteAddr)
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
|
||||
return rs.peers[r.RemoteAddr]
|
||||
}
|
||||
|
||||
func (rs *ReseederImpl) CreateSu3(seeds Seed) (*su3.Su3File, error) {
|
||||
su3File := su3.NewSu3File()
|
||||
su3File.FileType = su3.FILE_TYPE_ZIP
|
||||
su3File.ContentType = su3.CONTENT_TYPE_RESEED
|
||||
|
||||
zipped, err := zipSeeds(seeds)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
su3File.SetContent(zipped)
|
||||
|
||||
return su3File, nil
|
||||
}
|
||||
|
||||
type NetDbProvider interface {
|
||||
// Get all router infos
|
||||
RouterInfos() ([]routerInfo, error)
|
||||
}
|
||||
|
||||
type LocalNetDbImpl struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func NewLocalNetDb(path string) *LocalNetDbImpl {
|
||||
return &LocalNetDbImpl{
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
|
||||
func (db *LocalNetDbImpl) RouterInfos() (routerInfos []routerInfo, err error) {
|
||||
var src []os.FileInfo
|
||||
if src, err = ioutil.ReadDir(db.Path); nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
// randomize the file order
|
||||
files := make([]os.FileInfo, len(src))
|
||||
perm := rand.Perm(len(src))
|
||||
for i, v := range perm {
|
||||
files[v] = src[i]
|
||||
}
|
||||
|
||||
r, _ := regexp.Compile("^routerInfo-[A-Za-z0-9-=~]+.dat$")
|
||||
|
||||
for _, file := range files {
|
||||
if r.MatchString(file.Name()) {
|
||||
riBytes, err := ioutil.ReadFile(filepath.Join(db.Path, file.Name()))
|
||||
if nil != err {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
routerInfos = append(routerInfos, routerInfo{
|
||||
Name: file.Name(),
|
||||
Data: riBytes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
4
reseed/service.go
Normal file
4
reseed/service.go
Normal file
@@ -0,0 +1,4 @@
|
||||
package reseed
|
||||
|
||||
type Su3Provider interface {
|
||||
}
|
||||
32
reseed/utils.go
Normal file
32
reseed/utils.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package reseed
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func zipSeeds(seeds Seed) ([]byte, error) {
|
||||
// Create a buffer to write our archive to.
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Create a new zip archive.
|
||||
zipWriter := zip.NewWriter(buf)
|
||||
|
||||
// Add some files to the archive.
|
||||
for _, file := range seeds {
|
||||
zipFile, err := zipWriter.Create(file.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = zipFile.Write(file.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := zipWriter.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
@@ -19,6 +19,38 @@ func certForSigner(signer string) (*x509.Certificate, error) {
|
||||
|
||||
var (
|
||||
reseedKeys = map[string][]byte{
|
||||
"matt@drollette.com": []byte(`-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
5wYKnjW5pFMnWeBlDXkVUPOIM+/paw==
|
||||
-----END CERTIFICATE-----`),
|
||||
"backup@mail.i2p": []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIFfTCCA2WgAwIBAgIEOprmhjANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY
|
||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
||||
|
||||
143
su3/su3.go
143
su3/su3.go
@@ -3,14 +3,20 @@ package su3
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
MAGIC_BYTES = "I2Psu3"
|
||||
MAGIC_BYTES = "I2Psu3"
|
||||
MIN_VERSION_LENGTH = 16
|
||||
|
||||
SIGTYPE_DSA = uint16(0)
|
||||
SIGTYPE_ECDSA_SHA256 = uint16(1)
|
||||
@@ -34,14 +40,14 @@ const (
|
||||
|
||||
type Su3File struct {
|
||||
Magic [6]byte
|
||||
Format [1]byte
|
||||
Format uint8
|
||||
SignatureType uint16
|
||||
SignatureLength uint16
|
||||
VersionLength uint8
|
||||
SignerIdLength uint8
|
||||
ContentLength uint64
|
||||
FileType [1]byte
|
||||
ContentType [1]byte
|
||||
FileType uint8
|
||||
ContentType uint16
|
||||
|
||||
Version []byte
|
||||
SignerId []byte
|
||||
@@ -50,6 +56,129 @@ type Su3File struct {
|
||||
SignedBytes []byte
|
||||
}
|
||||
|
||||
func NewSu3File() *Su3File {
|
||||
var a [6]byte
|
||||
copy(a[:], MAGIC_BYTES)
|
||||
s := Su3File{Magic: a}
|
||||
s.SetVersion(strconv.FormatInt(time.Now().Unix(), 10))
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *Su3File) SetSignerId(signer string) {
|
||||
s.SignerId = []byte(signer)
|
||||
s.SignerIdLength = uint8(len(s.SignerId))
|
||||
}
|
||||
|
||||
func (s *Su3File) SetContent(content []byte) {
|
||||
s.Content = content
|
||||
s.ContentLength = uint64(len(s.Content))
|
||||
}
|
||||
|
||||
func (s *Su3File) SetVersion(version string) {
|
||||
s.Version = []byte(version)
|
||||
|
||||
minBytes := make([]byte, MIN_VERSION_LENGTH)
|
||||
if len(s.Version) < len(minBytes) {
|
||||
copy(minBytes, s.Version)
|
||||
s.Version = minBytes
|
||||
}
|
||||
|
||||
s.VersionLength = uint8(len(s.Version))
|
||||
}
|
||||
|
||||
func (s *Su3File) Sign(privkey *rsa.PrivateKey, sigType uint16) error {
|
||||
var hashType crypto.Hash
|
||||
switch sigType {
|
||||
// case SIGTYPE_DSA:
|
||||
// case SIGTYPE_ECDSA_SHA256:
|
||||
// case SIGTYPE_ECDSA_SHA384:
|
||||
// case SIGTYPE_ECDSA_SHA512:
|
||||
// case SIGTYPE_RSA_SHA256:
|
||||
// case SIGTYPE_RSA_SHA384:
|
||||
case SIGTYPE_RSA_SHA512:
|
||||
s.SignatureType = SIGTYPE_RSA_SHA512
|
||||
s.SignatureLength = uint16(512)
|
||||
hashType = crypto.SHA512
|
||||
default:
|
||||
return fmt.Errorf("Unknown signature type")
|
||||
}
|
||||
|
||||
h := hashType.New()
|
||||
h.Write(s.ContentBytes())
|
||||
digest := h.Sum(nil)
|
||||
|
||||
sig, err := rsa.SignPKCS1v15(rand.Reader, privkey, 0, digest)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Signature = sig
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Su3File) ContentBytes() []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
var (
|
||||
skip [1]byte
|
||||
bigSkip [12]byte
|
||||
)
|
||||
|
||||
// 0-5
|
||||
binary.Write(buf, binary.BigEndian, s.Magic)
|
||||
// 6
|
||||
binary.Write(buf, binary.BigEndian, skip)
|
||||
// 7
|
||||
binary.Write(buf, binary.BigEndian, s.Format)
|
||||
// 8-9
|
||||
binary.Write(buf, binary.BigEndian, s.SignatureType)
|
||||
// 10-11
|
||||
binary.Write(buf, binary.BigEndian, s.SignatureLength)
|
||||
// 12
|
||||
binary.Write(buf, binary.BigEndian, skip)
|
||||
// 13
|
||||
binary.Write(buf, binary.BigEndian, s.VersionLength)
|
||||
// 14
|
||||
binary.Write(buf, binary.BigEndian, skip)
|
||||
// 15
|
||||
binary.Write(buf, binary.BigEndian, s.SignerIdLength)
|
||||
// 16-23
|
||||
binary.Write(buf, binary.BigEndian, s.ContentLength)
|
||||
// 24
|
||||
binary.Write(buf, binary.BigEndian, skip)
|
||||
// 25
|
||||
binary.Write(buf, binary.BigEndian, s.FileType)
|
||||
// 26
|
||||
binary.Write(buf, binary.BigEndian, skip)
|
||||
// 27
|
||||
binary.Write(buf, binary.BigEndian, s.ContentType)
|
||||
// 28-39
|
||||
binary.Write(buf, binary.BigEndian, bigSkip)
|
||||
// 40-55+ Version, UTF-8 padded with trailing 0x00, 16 bytes minimum, length specified at byte 13. Do not append 0x00 bytes if the length is 16 or more.
|
||||
binary.Write(buf, binary.BigEndian, s.Version)
|
||||
// xx+ ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified at byte 15
|
||||
binary.Write(buf, binary.BigEndian, s.SignerId)
|
||||
// xx+ Content, length and format specified in header
|
||||
binary.Write(buf, binary.BigEndian, s.Content)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (s *Su3File) Bytes() []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.Write(s.ContentBytes())
|
||||
|
||||
// xx+ Signature, length specified in header, covers everything starting at byte 0
|
||||
binary.Write(buf, binary.BigEndian, s.Signature)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (s *Su3File) VerifySignature() error {
|
||||
return verifySig(s.SignatureType, s.SignerId, s.Signature, s.SignedBytes)
|
||||
}
|
||||
|
||||
func (s *Su3File) String() string {
|
||||
var b bytes.Buffer
|
||||
|
||||
@@ -72,17 +201,13 @@ func (s *Su3File) String() string {
|
||||
fmt.Fprintf(&b, "Version: %q\n", bytes.Trim(s.Version, "\x00"))
|
||||
fmt.Fprintf(&b, "SignerId: %q\n", s.SignerId)
|
||||
// fmt.Fprintf(&b, "Content: %q\n", s.Content)
|
||||
// fmt.Fprintf(&b, "Signature: %q\n", s.Signature)
|
||||
fmt.Fprintf(&b, "Signature: %q\n", s.Signature)
|
||||
|
||||
fmt.Fprintln(&b, "---------------------------")
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (s *Su3File) VerifySignature() error {
|
||||
return verifySig(s.SignatureType, s.SignerId, s.Signature, s.SignedBytes)
|
||||
}
|
||||
|
||||
func uzipData(c []byte) ([]byte, error) {
|
||||
input := bytes.NewReader(c)
|
||||
zipReader, err := zip.NewReader(input, int64(len(c)))
|
||||
|
||||
Reference in New Issue
Block a user