add a command to verify all public reseeders

This commit is contained in:
Matt Drollette
2014-12-10 19:17:12 -06:00
parent 4be2dbe247
commit ce34022e93
4 changed files with 134 additions and 68 deletions

View File

@@ -25,7 +25,7 @@ func su3VerifyAction(c *cli.Context) {
}
defer file.Close()
su3File, err := su3.ReadSu3(file)
su3File, err := su3.Parse(file)
if err != nil {
panic(err)
}
@@ -36,5 +36,5 @@ func su3VerifyAction(c *cli.Context) {
panic(err)
}
fmt.Println("Verified signature.")
fmt.Printf("Signature is valid for signer '%s'\n", su3File.SignerId)
}

102
cmd/verify_public.go Normal file
View File

@@ -0,0 +1,102 @@
package cmd
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"sync"
"github.com/MDrollette/go-i2p/su3"
"github.com/codegangsta/cli"
)
func NewSu3VerifyPublicCommand() cli.Command {
return cli.Command{
Name: "vp",
Usage: "Verify all publicly listed reseed servers",
Description: "Verify all publicly listed reseed servers",
Action: su3VerifyPublicAction,
Flags: []cli.Flag{},
}
}
func su3VerifyPublicAction(c *cli.Context) {
public_servers := []string{
"https://reseed.i2p-projekt.de/",
"https://cowpuncher.drollette.com/netdb/",
"https://i2p.mooo.com/netDb/",
"https://193.150.121.66/netDb/",
"https://netdb.i2p2.no/",
"https://reseed.info/",
"https://us.reseed.i2p2.no:444/",
"https://uk.reseed.i2p2.no:444/",
"https://i2p-netdb.innovatio.no/",
"https://ssl.webpack.de/ivae2he9.sg4.e-plaza.de/",
"https://link.mx24.eu/",
"https://ieb9oopo.mooo.com/",
}
pipe := make(chan *http.Response)
// Kick off goroutines to download the URLs
go download(pipe, public_servers)
// Process them serially
validate(pipe)
}
func download(out chan *http.Response, urls []string) {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := http.Client{Transport: tr}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go func(url string) {
defer wg.Done()
req, err := http.NewRequest("GET", fmt.Sprintf("%si2pseeds.su3", url), nil)
if err != nil {
log.Fatalln(err)
}
req.Header.Set("User-Agent", "Wget/1.11.4")
resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
out <- resp
}(url)
}
wg.Wait()
close(out)
}
func validate(in chan *http.Response) {
for resp := range in {
fmt.Printf("Validating: %s\n", resp.Request.URL)
if resp.StatusCode != 200 {
fmt.Printf("Invalid: Response code: %d\n", resp.StatusCode)
fmt.Println("")
continue
}
su3File, err := su3.Parse(resp.Body)
if err != nil {
fmt.Println("Invalid: Unable to parse SU3 file:", err)
}
resp.Body.Close()
if err := su3File.VerifySignature(); nil != err {
fmt.Println("Invalid: Unable to verify signature", err)
} else {
fmt.Printf("Valid: For signer '%s'\n", su3File.SignerId)
}
fmt.Println("")
}
}

View File

@@ -18,6 +18,7 @@ func main() {
cmd.NewSu3VerifyCommand(),
cmd.NewKeygenCommand(),
cmd.NewSu3Command(),
cmd.NewSu3VerifyPublicCommand(),
}
if err := app.Run(os.Args); err != nil {

View File

@@ -9,7 +9,7 @@ import (
"crypto/x509"
"encoding/binary"
"fmt"
"os"
"io"
"strconv"
"time"
)
@@ -79,7 +79,7 @@ func (s *Su3File) Sign(privkey *rsa.PrivateKey) error {
}
h := hashType.New()
h.Write(s.ContentBytes())
h.Write(s.BodyBytes())
digest := h.Sum(nil)
sig, err := rsa.SignPKCS1v15(rand.Reader, privkey, 0, digest)
@@ -92,7 +92,7 @@ func (s *Su3File) Sign(privkey *rsa.PrivateKey) error {
return nil
}
func (s *Su3File) ContentBytes() []byte {
func (s *Su3File) BodyBytes() []byte {
buf := new(bytes.Buffer)
var (
@@ -100,7 +100,7 @@ func (s *Su3File) ContentBytes() []byte {
bigSkip [12]byte
versionLength = uint8(len(s.Version))
signatureLength = uint16(40)
signatureLength = uint16(512)
signerIdLength = uint8(len(s.SignerId))
contentLength = uint64(len(s.Content))
)
@@ -124,41 +124,23 @@ func (s *Su3File) ContentBytes() []byte {
versionLength = uint8(len(s.Version))
}
// 0-5
binary.Write(buf, binary.BigEndian, MAGIC_BYTES)
// 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, signatureLength)
// 12
binary.Write(buf, binary.BigEndian, skip)
// 13
binary.Write(buf, binary.BigEndian, versionLength)
// 14
binary.Write(buf, binary.BigEndian, skip)
// 15
binary.Write(buf, binary.BigEndian, signerIdLength)
// 16-23
binary.Write(buf, binary.BigEndian, 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()
@@ -166,7 +148,7 @@ func (s *Su3File) ContentBytes() []byte {
func (s *Su3File) Bytes() []byte {
buf := new(bytes.Buffer)
buf.Write(s.ContentBytes())
buf.Write(s.BodyBytes())
// xx+ Signature, length specified in header, covers everything starting at byte 0
binary.Write(buf, binary.BigEndian, s.Signature)
@@ -198,7 +180,7 @@ func (s *Su3File) VerifySignature() error {
if cert, err := signerCertificate(string(s.SignerId)); nil != err {
return err
} else {
return checkSignature(cert, sigAlg, s.ContentBytes(), s.Signature)
return checkSignature(cert, sigAlg, s.BodyBytes(), s.Signature)
}
}
@@ -213,7 +195,7 @@ func (s *Su3File) String() string {
fmt.Fprintf(&b, "ContentType: %q\n", s.ContentType)
fmt.Fprintf(&b, "Version: %q\n", bytes.Trim(s.Version, "\x00"))
fmt.Fprintf(&b, "SignerId: %q\n", s.SignerId)
fmt.Fprintln(&b, "---------------------------")
fmt.Fprintf(&b, "---------------------------")
// content & signature
// fmt.Fprintf(&b, "Content: %q\n", s.Content)
@@ -243,64 +225,45 @@ func uzipData(c []byte) ([]byte, error) {
return uncompressed, nil
}
func ReadSu3(file *os.File) (*Su3File, error) {
func Parse(r io.Reader) (*Su3File, error) {
var (
s = Su3File{}
skip uint8
magic = MAGIC_BYTES
skip [1]byte
bigSkip [12]byte
signatureLength uint16
versionLength uint8
signerIdLength uint8
contentLength uint64
magic [6]byte
)
// 0-5
binary.Read(file, binary.BigEndian, &magic)
// 6
binary.Read(file, binary.BigEndian, &skip)
// 7
binary.Read(file, binary.BigEndian, &s.Format)
// 8-9
binary.Read(file, binary.BigEndian, &s.SignatureType)
// 10-11
binary.Read(file, binary.BigEndian, &signatureLength)
// 12
binary.Read(file, binary.BigEndian, &skip)
// 13
binary.Read(file, binary.BigEndian, &versionLength)
// 14
binary.Read(file, binary.BigEndian, &skip)
// 15
binary.Read(file, binary.BigEndian, &signerIdLength)
// 16-23
binary.Read(file, binary.BigEndian, &contentLength)
// 24
binary.Read(file, binary.BigEndian, &skip)
// 25
binary.Read(file, binary.BigEndian, &s.FileType)
// 26
binary.Read(file, binary.BigEndian, &skip)
// 27
binary.Read(file, binary.BigEndian, &s.ContentType)
// 28-39
binary.Read(file, binary.BigEndian, &bigSkip)
binary.Read(r, binary.BigEndian, &magic)
binary.Read(r, binary.BigEndian, &skip)
binary.Read(r, binary.BigEndian, &s.Format)
binary.Read(r, binary.BigEndian, &s.SignatureType)
binary.Read(r, binary.BigEndian, &signatureLength)
binary.Read(r, binary.BigEndian, &skip)
binary.Read(r, binary.BigEndian, &versionLength)
binary.Read(r, binary.BigEndian, &skip)
binary.Read(r, binary.BigEndian, &signerIdLength)
binary.Read(r, binary.BigEndian, &contentLength)
binary.Read(r, binary.BigEndian, &skip)
binary.Read(r, binary.BigEndian, &s.FileType)
binary.Read(r, binary.BigEndian, &skip)
binary.Read(r, binary.BigEndian, &s.ContentType)
binary.Read(r, binary.BigEndian, &bigSkip)
s.Version = make([]byte, versionLength)
s.SignerId = make([]byte, signerIdLength)
s.Content = make([]byte, contentLength)
s.Signature = make([]byte, signatureLength)
// 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.Read(file, binary.BigEndian, &s.Version)
// xx+ ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified at byte 15
binary.Read(file, binary.BigEndian, &s.SignerId)
// xx+ Content, length and format specified in header
binary.Read(file, binary.BigEndian, &s.Content)
// xx+ Signature, length specified in header, covers everything starting at byte 0
binary.Read(file, binary.BigEndian, &s.Signature)
binary.Read(r, binary.BigEndian, &s.Version)
binary.Read(r, binary.BigEndian, &s.SignerId)
binary.Read(r, binary.BigEndian, &s.Content)
binary.Read(r, binary.BigEndian, &s.Signature)
return &s, nil
}