From 8b93448bcd1bc3b9f87362cebcad49471f9f0770 Mon Sep 17 00:00:00 2001 From: Willie Koomson Date: Wed, 7 Mar 2018 21:03:46 -0500 Subject: [PATCH] Finished Crypto --- crypto.go | 8 +-- destination.go | 151 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 destination.go diff --git a/crypto.go b/crypto.go index be46360..91718fa 100644 --- a/crypto.go +++ b/crypto.go @@ -174,7 +174,7 @@ func (c *Crypto) SignatureKeyPairFromStream(stream *Stream) (sgk SignatureKeyPai } // Generate a signature keypair -func (c *Crypto) SignatureKeygen(algorithmTyp uint8) (sgk SignatureKeyPair, err error) { +func (c *Crypto) SignatureKeygen(algorithmTyp uint32) (sgk SignatureKeyPair, err error) { var pkey dsa.PrivateKey pkey.G = c.params.G pkey.Q = c.params.Q @@ -206,12 +206,12 @@ func (c *Crypto) EncodeStream(algorithmTyp uint8, src *Stream) (dst Stream) { } return } -func (c *Crypto) DecodeStream(algorithmTyp uint8, src *Stream) (dst Stream) { +func (c *Crypto) DecodeStream(algorithmTyp uint8, src *Stream) (dst Stream, err error) { switch algorithmTyp { case CODEC_BASE32: - c.b32.Decode(dst.Bytes(), src.Bytes()) + _, err = c.b32.Decode(dst.Bytes(), src.Bytes()) case CODEC_BASE64: - c.b64.Decode(dst.Bytes(), src.Bytes()) + _, err = c.b64.Decode(dst.Bytes(), src.Bytes()) } return } diff --git a/destination.go b/destination.go new file mode 100644 index 0000000..3cd2d28 --- /dev/null +++ b/destination.go @@ -0,0 +1,151 @@ +package go_i2cp + +import ( + "crypto" + "errors" + "github.com/cryptix/go/crypt" + "math/big" + "os" + "strings" +) + +const tag = DESTINATION +const PUB_KEY_SIZE = 256 +const DIGEST_SIZE = 40 +const DEST_SIZE = 4096 + +type Destination struct { + cert *Certificate + sgk SignatureKeyPair + signPubKey *big.Int + pubKey []byte + digest [DIGEST_SIZE]byte + b32 string + b64 string +} + +func NewDestination() (dest Destination, err error) { + nullCert := NewCertificate(CERTIFICATE_NULL) + dest.cert = &nullCert + dest.sgk, err = GetCryptoInstance().SignatureKeygen(DSA_SHA1) + dest.generateB32() + dest.generateB64() + return +} + +// TODO ensure that this function not setting dest.sgk is the right thing to do +func NewDestinationFromMessage(stream *Stream) (dest Destination, err error) { + signPubKey := make([]byte, 128) + pubKey := make([]byte, PUB_KEY_SIZE) + _, err = stream.Read(pubKey) + _, err = stream.Read(signPubKey) + dest.pubKey = pubKey + dest.signPubKey.SetBytes(signPubKey) + var cert Certificate + cert, err = NewCertificateFromMessage(stream) + dest.cert = &cert + dest.generateB32() + dest.generateB64() + return +} + +func NewDestinationFromStream(stream *Stream) (dest Destination, err error) { + var cert Certificate + var pubKeyLen uint16 + cert, err = NewCertificateFromStream(stream) + dest.cert = &cert + dest.sgk, err = GetCryptoInstance().SignatureKeyPairFromStream(stream) + pubKeyLen, err = stream.ReadUint16() + if pubKeyLen != PUB_KEY_SIZE { + Fatal(tag, "Failed to load pub key len, %d != %d", pubKeyLen, PUB_KEY_SIZE) + } + pubKey := make([]byte, PUB_KEY_SIZE) + _, err = stream.Read(pubKey) + dest.pubKey = pubKey + dest.generateB32() + dest.generateB64() + return +} + +func NewDestinationFromBase64(base64 string) (dest Destination, err error) { + /* Same as decode, except from a filesystem / URL friendly set of characters, + * replacing / with ~, and + with - + */ + // see https://javadoc.freenetproject.org/freenet/support/Base64.html + if len(base64) == 0 { + err = errors.New("empty string") + return + } + var replaced string + // Convert from freenet to standard + replaced = strings.Replace(base64, "~", "/", -1) + replaced = strings.Replace(replaced, "-", "+", -1) + stream := NewStream([]byte(replaced)) + var decoded Stream + decoded, err = GetCryptoInstance().DecodeStream(CODEC_BASE64, stream) + return NewDestinationFromMessage(&decoded) +} + +func NewDestinationFromFile(file os.File) (dest Destination, err error) { + var stream Stream + stream.loadFile(file) + return NewDestinationFromStream(&stream) +} +func (dest *Destination) Copy() (newDest Destination) { + newDest.cert = dest.cert + newDest.signPubKey = dest.signPubKey + copy(newDest.pubKey, dest.pubKey) + newDest.sgk = dest.sgk + newDest.b32 = dest.b32 + newDest.b64 = dest.b64 + newDest.digest = dest.digest + return +} +func (dest *Destination) WriteToFile(filename string) (err error) { + stream := NewStream(make([]byte, DEST_SIZE)) + dest.WriteToStream(stream) + var file *os.File + file, err = os.Open(filename) + stream.WriteTo(file) + file.Close() +} +func (dest *Destination) WriteToMessage(stream *Stream) (err error) { + _, err = stream.Write(dest.pubKey) + _, err = stream.Write(dest.signPubKey.Bytes()) //GetCryptoInstance().WriteSignatureToStream(&dest.sgk, stream) + err = dest.cert.WriteToMessage(stream) + return +} +func (dest *Destination) WriteToStream(stream *Stream) (err error) { + err = dest.cert.WriteToStream(stream) + err = GetCryptoInstance().WriteSignatureToStream(&dest.sgk, stream) + err = stream.WriteUint16(PUB_KEY_SIZE) + _, err = stream.Write(dest.pubKey) + return +} + +//Doesn't seem to be used anywhere?? +func (dest *Destination) Verify() (verified bool, err error) { + stream := NewStream(make([]byte, DEST_SIZE)) + dest.WriteToMessage(stream) + stream.Write(dest.digest[:]) + return GetCryptoInstance().VerifyStream(&dest.sgk, stream) +} + +func (dest *Destination) generateB32() { + stream := NewStream(make([]byte, DEST_SIZE)) + dest.WriteToMessage(stream) + cpt := GetCryptoInstance() + hash := cpt.HashStream(HASH_SHA256, stream) + b32 := cpt.EncodeStream(CODEC_BASE32, hash) + dest.b32 = string(b32.Bytes()) + ".b32.i2p" + Debug(tag, "New destination %s", dest.b32) +} +func (dest *Destination) generateB64() { + stream := NewStream(make([]byte, DEST_SIZE)) + dest.WriteToMessage(stream) + cpt := GetCryptoInstance() + b64B := cpt.EncodeStream(CODEC_BASE64, stream) + replaced := strings.Replace(string(b64B.Bytes()), "/", "~", -1) + replaced = strings.Replace(replaced, "/", "~", -1) + dest.b64 = replaced +}